using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
//using Sanford.Multimedia.Midi;
using System.Threading;
using System.Windows.Forms;
using NAudio.Midi;
using Microsoft.DirectX.DirectSound;
//using DirectMidi;

namespace MKDS_Course_Editor
{
	partial class sseq : Form
	{
		Players.MusicPlayer m;
		byte[] dls;
		byte[] buffer;
		MidiEventCollection mev = new MidiEventCollection(1, 48);
		List<SSEQ.SSEQEvent> ssev = new List<SSEQ.SSEQEvent>();
		List<List<SSEQ.SSEQEvent>> tracks = new List<List<SSEQ.SSEQEvent>>();
		List<int[]> offs = new List<int[]>();
		byte[] file;
		byte[] sbnk;
		bool sbnk_Used;
		string name;
		bool ssar = false;
		int ssaroffset;
		public sseq(string file, Players.MusicPlayer m)
		{
			this.file = File.ReadAllBytes(file);
			name = Path.GetFileName(file).Replace("\0", "");
			InitializeComponent();
			this.Text = string.Format("SSEQ Player - [{0}]", name);
			this.m = m;
		}
		public sseq()
		{
		}
		public sseq(byte[] file, string name, byte[] dls, Players.MusicPlayer m)
		{
			this.dls = dls;
			this.file = file;
			this.name = name.Replace("\0", "");
			InitializeComponent();
			this.Text = string.Format("SSEQ Player - [{0}]", this.name);
			this.m = m;
			if (dls != null)
			{
				toolStripButton7.Enabled = true;
			}
		}
		public sseq(byte[] notes, int offset, byte[] dls, Players.MusicPlayer m)
		{
			this.dls = dls;
			this.file = notes;
			InitializeComponent();
			this.m = m;
			ssar = true;
			ssaroffset = offset;
			this.Text = "SSAR Player";
			if (dls != null)
			{
				toolStripButton7.Enabled = true;
			}
		}
		public sseq(byte[] file, byte[] sbnk, Players.MusicPlayer m)
		{
			this.file = file;
			this.sbnk = sbnk;
			InitializeComponent();
			this.m = m;
		}
		int loopstart = -1;
		int loopend = -1;
		short[] vars = new short[255];
		int nrloop = -1;
		private void sseq_Load(object sender, EventArgs e)
		{
			/*// Initializes DirectMusic
			CDMusic.Initialize();
			// Initializes an audiopath performance
			CAPathPerformance.Initialize(CDMusic, null, null, DirectMidi.DMUS_APATH.DYNAMIC_STEREO, 128);
			// Initializes a port performance object
			//CPortPerformance.Initialize(CDMusic, null, null);
			// Initializes loader object
			CLoader.Initialize();
			// Initializes output port
			COutPort.Initialize(CDMusic);
			// Selects the first software synthesizer port
			DirectMidi.INFOPORT PortInfo;
			uint dwPortCount = 0;
			//do
			COutPort.GetPortInfo(dwPortCount, out PortInfo);
			//while (!(PortInfo.dwFlags.HasFlag(DirectMidi.DMUS_PC.SOFTWARESYNTH)));
			//cout << "Selected output port: " << PortInfo.szPortDescription << endl;
			COutPort.SetPortParams(0, 0, 0, DirectMidi.SET.REVERB | DirectMidi.SET.CHORUS, 44100);
			COutPort.ActivatePort(PortInfo);
			// Adds the selected port to the performance
			//CAPathPerformance.AddPort(COutPort, 0, 1);*/


			imageList1.Images.Add(Properties.Resources.guitar);
			imageList1.Images.Add(Properties.Resources.Treble_20Clef);
			imageList1.Images.Add(Properties.Resources.music_beam_16);
			imageList1.Images.Add(Properties.Resources.metronome);
			imageList1.Images.Add(Properties.Resources.rest);
			imageList1.Images.Add(Properties.Resources.sound);
			imageList1.Images.Add(Properties.Resources.pitch);
			EndianBinaryReader er = new EndianBinaryReader(new MemoryStream(file), Endianness.LittleEndian);
			if (er.ReadString(Encoding.ASCII, 4) == "SSEQ" || ssar) // 'SSEQ'
			{
				if (!ssar)
				{
					er.ReadBytes(4); // 0x0100feff
					er.ReadInt32(); // Size of this SSEQ file
					er.ReadInt16(); // Size of this structure = 16
					er.ReadInt16(); // Number of Blocks = 1
				}
				if (er.ReadString(Encoding.ASCII, 4) == "DATA" || ssar) // 'DATA'
				{
					if (!ssar)
					{
						er.ReadInt32(); // Size of this structure = nFileSize - 16
						er.ReadInt32();	// Offset of the sequence data = 0x1c
					}
					//Sanford.Multimedia.Midi.Sequence s = new Sanford.Multimedia.Midi.Sequence();
					//s.Add(new Sanford.Multimedia.Midi.Track());
					int nrtrack = 0;
					int realtrack = 1;
					bool isfirst = true;
					bool isfirst2 = true;
					float tempo = 10;
					int curtrack = -1;
					int curtime = 0;
					List<int> offset = new List<int>();
					double bpm = 0;
					int note1 = -1;
					int note2 = -1;
					int returnoffset = 0;
					int nr_ = 1;
					bool notewait = false;
					int returnpos = 0;
					bool loop = false;
					int lasttime = 0;
					bool drums = false;
					bool gotdrum = false;
					int lasttrack = -1;
					if (ssar)
					{
						//offset.Add(ssaroffset);
						er.BaseStream.Position = ssaroffset;
						//if (loop == false)
						//{
						//er.BaseStream.Position -= 4;
						//ssev.Add(new SSEQ.SSEQEvent(nr, er.ReadBytes(4)));
						//treeView1.Nodes.Add("Open Track");
						//}
					}
					List<int> time = new List<int>();
					Dictionary<int, int> byte2time = new Dictionary<int, int>();
					mev.AddTrack();
					curtrack += 1;
					curtime = 0;
					checkedListBox1.Items.Add("Track " + (curtrack + 1).ToString(), true);
					treeView1.Nodes.Insert(curtrack, "Track " + (curtrack + 1).ToString());
					treeView1.Nodes[curtrack].SelectedImageIndex = 1;
					treeView1.Nodes[curtrack].ImageIndex = 1;
					bool statement = true;
					bool excutestatement = false;
					if (er.ReadByte() == 0xFE)
					{
						er.ReadInt16();
						//if (loop == false)
						//{
						er.BaseStream.Position -= 2;
						ssev.Add(new SSEQ.SSEQEvent(0xFE, er.ReadBytes(2)));
						treeView1.Nodes.Add("Multitrack");
						//}
						while (er.ReadByte() == 0x80)
						{
							int delay;
							delay = smfReadVarLength(er);
							//Thread.Sleep((int)(delay * (60000f / (bpm * 96f))));
							//curtime += delay;
							//if (loop == false)
							//{
							treeView1.Nodes.Add("Rest (" + delay + ")");
							treeView1.Nodes[treeView1.Nodes.Count - 1].ImageIndex = 4;
							treeView1.Nodes[treeView1.Nodes.Count - 1].SelectedImageIndex = 4;
							er.BaseStream.Position -= smfGetVarLengthSize(delay);
							ssev.Add(new SSEQ.SSEQEvent(0x80, er.ReadBytes(smfGetVarLengthSize(delay))));
							//}
						}
						er.BaseStream.Position -= 1;
						while (er.ReadByte() == 0x93)
						{
							int newTrackIndex = er.ReadByte();
							byte[] b2_ = er.ReadBytes(3);
							Array.Reverse(b2_);
							int off2 = int.Parse(BitConverter.ToString(b2_).Replace("-", ""), System.Globalization.NumberStyles.HexNumber);
							offset.Add(off2);
							nrtrack += 1;
							//if (loop == false)
							//{
							er.BaseStream.Position -= 4;
							ssev.Add(new SSEQ.SSEQEvent(0x93, er.ReadBytes(4)));
							treeView1.Nodes.Add("Open Track");
							//}
						}
						er.BaseStream.Position -= 1;
					}
					byte lastevent = 00;
					while (er.BaseStream.Position != er.BaseStream.Length)
					{
						if (offset.Contains((int)er.BaseStream.Position - 0x1c) && !loop && lastevent != 0xFF)
						{
							mev[curtrack].Add(new MetaEvent(MetaEventType.EndTrack, 0, lasttime));
							SSEQ.SSEQEvent[] s = new SSEQ.SSEQEvent[ssev.Count];
							ssev.CopyTo(s);
							tracks.Add(s.ToList());
							ssev.Clear();
							if (nrtrack == curtrack)
							{
								goto end;
							}
							if (nrtrack != curtrack)
							{
								//er.BaseStream.Position = offset[curtrack] + (ssar ? 0 : 0x1C);
								mev.AddTrack();
								curtrack += 1;
								realtrack += 1;
								if (realtrack == 11)
								{
									realtrack = lasttrack;
								}
								lasttime = 0;
								if (realtrack == 10)
								{
									realtrack++;
								}
								//if (realtrack == 17)
								//{
								//	realtrack = 1;
								//}
								vars = new short[255];
								curtime = 0;
								checkedListBox1.Items.Add("Track " + (curtrack + 1).ToString(), true);
								treeView1.Nodes.Insert(curtrack, "Track " + (curtrack + 1).ToString());
								treeView1.Nodes[curtrack].SelectedImageIndex = 1;
								treeView1.Nodes[curtrack].ImageIndex = 1;
							}
						}
						if (lasttime < curtime)
						{
							lasttime = curtime;
						}
						time.Add(curtime);
						if (curtrack == 0)
						{
							if (!byte2time.ContainsKey((int)er.BaseStream.Position - 0x1C))
							{
								byte2time.Add((int)er.BaseStream.Position - 0x1C, curtime);
							}
						}
						byte nr = er.ReadByte();
						if (nr < 0x80)
						{
							int velocity = Convert.ToInt32(er.ReadByte());
							int duration = smfReadVarLength(er);
							if (loop == false)
							{
								er.BaseStream.Position -= smfGetVarLengthSize(duration) + 1;
								ssev.Add(new SSEQ.SSEQEvent(nr, er.ReadBytes(smfGetVarLengthSize(duration) + 1)));
								treeView1.Nodes[curtrack].Nodes.Add("Note (" + nr + ")");
								treeView1.Nodes[curtrack].Nodes[treeView1.Nodes[curtrack].Nodes.Count - 1].ImageIndex = 2;
								treeView1.Nodes[curtrack].Nodes[treeView1.Nodes[curtrack].Nodes.Count - 1].SelectedImageIndex = 2;
							}
							if (note1 != -1)
							{

							}


							if (velocity > 127)
							{
								//er.BaseStream.Position -= 1;
								velocity = 127;
							}
							mev[curtrack].Add(new NoteEvent(curtime, realtrack, MidiCommandCode.NoteOn, nr, velocity));
							if (duration != 0)
							{
								mev[curtrack].Add(new NoteEvent(curtime + duration, realtrack, MidiCommandCode.NoteOff, nr, 64));
							}
							if (notewait)
							{
								curtime += duration;
							}
							if (lasttime < curtime + duration)
							{
								lasttime = curtime + duration;
							}
						}

						else
						{
							byte b;
							switch (nr)
							{
								case 0x80:
									int delay;
									delay = smfReadVarLength(er);
									//Thread.Sleep((int)(delay * (60000f / (bpm * 96f))));
									curtime += delay;
									if (loop == false)
									{
										treeView1.Nodes[curtrack].Nodes.Add("Rest (" + delay + ")");
										treeView1.Nodes[curtrack].Nodes[treeView1.Nodes[curtrack].Nodes.Count - 1].ImageIndex = 4;
										treeView1.Nodes[curtrack].Nodes[treeView1.Nodes[curtrack].Nodes.Count - 1].SelectedImageIndex = 4;
										er.BaseStream.Position -= smfGetVarLengthSize(delay);
										ssev.Add(new SSEQ.SSEQEvent(nr, er.ReadBytes(smfGetVarLengthSize(delay))));
									}
									break;
								case 0x81:
									/*byte inst = er.ReadByte();
									mev[curtrack].Insert(0, new PatchChangeEvent(curtime, curtrack+1, inst));
									//z = new MidiEvent(outDevice, curtime, new ChannelMessage(ChannelCommand.Controller, curtrack, 0x00, inst));
									//outDevice.Write(z);*/
									int realProgram;
									int bankMsb;
									int bankLsb;
									int program;

									realProgram = smfReadVarLength(er);
									program = realProgram % 128;
									bankLsb = (realProgram / 128) & 15;
									bankMsb = (realProgram / 128 / 128) & 15;
									mev[curtrack].Insert(0, ControlChangeEvent.FromRawMessage(MidiMessage.ChangeControl(0, bankMsb, realtrack).RawData));
									mev[curtrack].Insert(0, ControlChangeEvent.FromRawMessage(MidiMessage.ChangeControl(32, bankLsb, realtrack).RawData));
									mev[curtrack].Insert(0, new PatchChangeEvent(curtime, realtrack, program));
									if (program == 127)
									{
										drums = true;
										gotdrum = true;
										lasttrack = realtrack;
										realtrack = 10;
										foreach (MidiEvent ve in mev[curtrack])
										{
											ve.Channel = realtrack;
										}
									}
									if (loop == false)
									{
										treeView1.Nodes[curtrack].Nodes.Add("Bank Change (" + program + ")");
										er.BaseStream.Position -= smfGetVarLengthSize(realProgram);
										ssev.Add(new SSEQ.SSEQEvent(nr, er.ReadBytes(smfGetVarLengthSize(realProgram))));
									}
									//sprintf(eventName, "Program Change");
									//sprintf(eventDesc, "%d", realProgram);
									break;
								case 0x93:
									/*er.ReadByte();
									int off2 = int.Parse(BitConverter.ToString(er.ReadBytes(3)).Replace("-", ""), System.Globalization.NumberStyles.HexNumber);
									offset.Add(off2 + 0x1C);
									nrtrack += 1;
									break;*/
									int newTrackIndex = er.ReadByte();
									byte[] b2_ = er.ReadBytes(3);
									Array.Reverse(b2_);
									int off2 = int.Parse(BitConverter.ToString(b2_).Replace("-", ""), System.Globalization.NumberStyles.HexNumber);
									offset.Add(off2);
									nrtrack += 1;
									if (loop == false)
									{
										er.BaseStream.Position -= 4;
										ssev.Add(new SSEQ.SSEQEvent(nr, er.ReadBytes(4)));
										treeView1.Nodes.Add("Open Track");
									}
									break;
								case 0x94:
									{
										byte[] b2 = er.ReadBytes(3);
										Array.Reverse(b2);
										int off = int.Parse(BitConverter.ToString(b2).Replace("-", ""), System.Globalization.NumberStyles.HexNumber);
										//ControlChangeEvent c = (ControlChangeEvent)ControlChangeEvent.FromRawMessage(MidiMessage.ChangeControl(0x74, 0, curtrack).RawData);
										//c.AbsoluteTime = time[off];
										//mev[curtrack].Add(c);
										//mev[curtrack].Add(ControlChangeEvent.FromRawMessage(MidiMessage.ChangeControl(0x75, 0, curtrack).RawData));
										if (loop == false)
										{
											treeView1.Nodes[curtrack].Nodes.Add("Jump");
											er.BaseStream.Position -= 3;
											ssev.Add(new SSEQ.SSEQEvent(nr, er.ReadBytes(3)));
										}
										if (excutestatement && statement || !excutestatement)
										{
											try
											{
												if (loopend == -1)
												{
													loopend = curtime;
													loopstart = byte2time[off];
													mev[curtrack].Add(new TextEvent("loopEnd",MetaEventType.Marker, curtime));
													mev[curtrack].Add(new TextEvent("loopStart", MetaEventType.Marker, byte2time[off]));
												}
											}

											catch
											{
												loopend = -1;
												loopstart = -1;
											}
										}
										break;
									}
								case 0x95:
									{
										byte[] b2 = er.ReadBytes(3);
										Array.Reverse(b2);
										int off = int.Parse(BitConverter.ToString(b2).Replace("-", ""), System.Globalization.NumberStyles.HexNumber);
										returnoffset = (int)er.BaseStream.Position;
										if (loop == false)
										{
											treeView1.Nodes[curtrack].Nodes.Add("Call");
											er.BaseStream.Position -= 3;
											ssev.Add(new SSEQ.SSEQEvent(nr, er.ReadBytes(3)));
											offs.Add(new int[] { curtrack, treeView1.Nodes[curtrack].Nodes.Count, ssev.Count, off });
										}
										er.BaseStream.Seek(off + (ssar ? 0 : 0x1C), SeekOrigin.Begin);
										loop = true;
										break;
									}
								case 0xa0: /* Hanjuku Hero DS: NSE_45, New Mario Bros: BGM_AMB_CHIKA, Slime Morimori Dragon Quest 2: SE_187, SE_210, Advance Wars */
									{
										byte subStatusByte;
										int randMin;
										int randMax;

										subStatusByte = er.ReadByte();
										randMin = er.ReadInt16();
										randMax = er.ReadInt16();
										Random r = new Random();
										switch (subStatusByte)
										{
											case 0x80:
												curtime += r.Next(randMin, randMax);
												break;
											case 0xC0:
												int pann = (byte)r.Next(randMin, randMax);
												mev[curtrack].Add(new ControlChangeEvent(curtime, realtrack, MidiController.Pan, pann));
												break;
											case 0xC1:
												{
													int vol = (byte)r.Next(randMin, randMax);
													mev[curtrack].Add(new ControlChangeEvent(curtime, realtrack, MidiController.MainVolume, vol));
													break;
												}
											case 0xc4:
												short pbb = (short)r.Next(randMin, randMax);
												pbb = (short)((pbb + 128) * 64);
												if (!(pbb < 0 || pbb > 0x4000))
												{
													mev[curtrack].Add(new PitchWheelChangeEvent(curtime, realtrack, pbb));
												}
												break;
											default:
												break;
										}
										if (loop == false)
										{
											er.BaseStream.Position -= 5;
											ssev.Add(new SSEQ.SSEQEvent(nr, er.ReadBytes(5)));
											treeView1.Nodes[curtrack].Nodes.Add("Random");
										}
										break;
									}
								case 0xa1: /* New Mario Bros: BGM_AMB_SABAKU */
									{
										byte subStatusByte;
										int varNumber;

										subStatusByte = er.ReadByte();
										if (subStatusByte >= 0xb0 && subStatusByte <= 0xbd) /* var */
										{
											/* loveemu is a lazy person :P */
											int unknown = er.ReadByte();
											varNumber = er.ReadByte();
											if (loop == false)
											{
												er.BaseStream.Position -= 3;
												ssev.Add(new SSEQ.SSEQEvent(nr, er.ReadBytes(3)));
												treeView1.Nodes[curtrack].Nodes.Add("Var");
											}
										}
										else
										{

											varNumber = er.ReadByte();
											switch (subStatusByte)
											{
												case 0x80:
													curtime += vars[varNumber];
													break;
												case 0xC0:
													int pann = vars[varNumber];
													mev[curtrack].Add(new ControlChangeEvent(curtime, realtrack, MidiController.Pan, pann));
													break;
												case 0xC1:
													{
														int vol = vars[varNumber];
														mev[curtrack].Add(new ControlChangeEvent(curtime, realtrack, MidiController.MainVolume, vol));
														break;
													}
												case 0xc4:
													short pbb = vars[varNumber];
													pbb = (short)((pbb + 128) * 64);
													if (!(pbb < 0 || pbb > 0x4000))
													{
														mev[curtrack].Add(new PitchWheelChangeEvent(curtime, realtrack, pbb));
													}
													break;
												default:
													break;
											}
											if (loop == false)
											{
												er.BaseStream.Position -= 2;
												ssev.Add(new SSEQ.SSEQEvent(nr, er.ReadBytes(2)));
												treeView1.Nodes[curtrack].Nodes.Add("Var");
											}
										}
										break;
									}
								case 0xa2:
									{
										/* TODO: implement */
										excutestatement = true;
										if (loop == false)
										{
											ssev.Add(new SSEQ.SSEQEvent(nr, null));
											treeView1.Nodes[curtrack].Nodes.Add("If");
										}
										break;
									}
								case 0xb0: /* Children of Mana: SEQ_BGM001 */
								case 0xb1: /* Advance Wars - Dual Strike: SE_TAGPT_COUNT01 */
								case 0xb2:
								case 0xb3:
								case 0xb4:
								case 0xb5:
								case 0xb6: /* Mario Kart DS: 76th sequence */
								case 0xb8: /* Tottoko Hamutaro: MUS_ENDROOL, Nintendogs */
								case 0xb9:
								case 0xba:
								case 0xbb:
								case 0xbc:
								case 0xbd:
									{
										int varNumber;
										short var;
										string[] varMethodName = new string[] {
                                        "Set Variable", "Add Variable", "Sub Variable", "Mul Variable", "Div Variable", 
				"Shift Vabiable", "Rand Variable", "", "If Variable ==", "If Variable >=", 
				"If Variable >", "If Variable <=", "If Variable <", "If Variable !="
                                      };
										varNumber = er.ReadByte();
										var = er.ReadInt16();
										switch (nr - 0xB0)
										{
											case 0:
												vars[varNumber] = var;
												break;
											case 1:
												vars[varNumber] += var;
												break;
											case 2:
												vars[varNumber] -= var;
												break;
											case 3:
												vars[varNumber] *= var;
												break;
											case 4:
												vars[varNumber] /= var;
												break;
											case 5:
												vars[varNumber] >>= var;
												break;
											case 6:
												vars[varNumber] = (short)(new Random().Next(Int16.MaxValue));
												break;
											case 7:
												break;
											case 8:
												statement = vars[varNumber] == var;
												break;
											case 9:
												statement = vars[varNumber] >= var;
												break;
											case 10:
												statement = vars[varNumber] > var;
												break;
											case 11:
												statement = vars[varNumber] <= var;
												break;
											case 12:
												statement = vars[varNumber] < var;
												break;
											case 13:
												statement = vars[varNumber] != var;
												break;
										}
										if (loop == false)
										{
											treeView1.Nodes[curtrack].Nodes.Add(varMethodName[nr - 0xB0]);
											er.BaseStream.Position -= 3;
											ssev.Add(new SSEQ.SSEQEvent(nr, er.ReadBytes(3)));
										}
										break;
									}
								case 0xC0:
									int pan = er.ReadByte();
									mev[curtrack].Add(new ControlChangeEvent(curtime, realtrack, MidiController.Pan, pan));
									if (loop == false)
									{
										treeView1.Nodes[curtrack].Nodes.Add("Pan (" + (pan - 64).ToString() + ")");
										er.BaseStream.Position -= 1;
										ssev.Add(new SSEQ.SSEQEvent(nr, er.ReadBytes(1)));
									}
									break;
								case 0xC1:
									{
										int vol = er.ReadByte();
										mev[curtrack].Add(new ControlChangeEvent(curtime, realtrack, MidiController.MainVolume, vol));
										if (loop == false)
										{
											treeView1.Nodes[curtrack].Nodes.Add("Volume (" + vol.ToString() + ")");
											treeView1.Nodes[curtrack].Nodes[treeView1.Nodes[curtrack].Nodes.Count - 1].SelectedImageIndex = 5;
											treeView1.Nodes[curtrack].Nodes[treeView1.Nodes[curtrack].Nodes.Count - 1].ImageIndex = 5;
											er.BaseStream.Position -= 1;
											ssev.Add(new SSEQ.SSEQEvent(nr, er.ReadBytes(1)));
										}
										break;
									}
								case 0xC2:
									{
										int vol = er.ReadByte();
										mev[curtrack].Add(new SequencerSpecificEvent(new byte[] { 0xF0, 0x7F, 0x7F, 0x04, 0x01, 0x00, (byte)vol, 0xF7 }, curtime));
										if (loop == false)
										{
											treeView1.Nodes[curtrack].Nodes.Add("Master Volume (" + vol.ToString() + ")");
											treeView1.Nodes[curtrack].Nodes[treeView1.Nodes[curtrack].Nodes.Count - 1].SelectedImageIndex = 5;
											treeView1.Nodes[curtrack].Nodes[treeView1.Nodes[curtrack].Nodes.Count - 1].ImageIndex = 5;
											er.BaseStream.Position -= 1;
											ssev.Add(new SSEQ.SSEQEvent(nr, er.ReadBytes(1)));
										}
										break;
									}
								case 0xC3:
									mev[curtrack].Add(ControlChangeEvent.FromRawMessage(MidiMessage.ChangeControl(101, 0, realtrack).RawData));
									mev[curtrack].Add(ControlChangeEvent.FromRawMessage(MidiMessage.ChangeControl(100, 2, realtrack).RawData));
									mev[curtrack].Add(ControlChangeEvent.FromRawMessage(MidiMessage.ChangeControl(6, er.ReadByte() + 64, realtrack).RawData));
									if (loop == false)
									{
										er.BaseStream.Position -= 1;
										ssev.Add(new SSEQ.SSEQEvent(nr, er.ReadBytes(1)));
										treeView1.Nodes[curtrack].Nodes.Add("Transpose");
									}
									break;
								case 0xC4:
									short pb = er.ReadSByte();
									pb = (short)((pb + 128) * 64);
									if (!(pb < 0 || pb > 0x4000))
									{
										mev[curtrack].Add(new PitchWheelChangeEvent(curtime, realtrack, pb));
									}
									if (loop == false)
									{
										treeView1.Nodes[curtrack].Nodes.Add("Pitch Change");
										treeView1.Nodes[curtrack].Nodes[treeView1.Nodes[curtrack].Nodes.Count - 1].SelectedImageIndex = 6;
										treeView1.Nodes[curtrack].Nodes[treeView1.Nodes[curtrack].Nodes.Count - 1].ImageIndex = 6;
										er.BaseStream.Position -= 1;
										ssev.Add(new SSEQ.SSEQEvent(nr, er.ReadBytes(1)));
									}
									break;
								case 0xC5:
									int range = er.ReadByte();
									mev[curtrack].Add(ControlChangeEvent.FromRawMessage(MidiMessage.ChangeControl(101, 0, realtrack).RawData));
									mev[curtrack].Add(ControlChangeEvent.FromRawMessage(MidiMessage.ChangeControl(100, 0, realtrack).RawData));
									mev[curtrack].Add(ControlChangeEvent.FromRawMessage(MidiMessage.ChangeControl(6, range, realtrack).RawData));
									if (loop == false)
									{
										treeView1.Nodes[curtrack].Nodes.Add("Pitch Range");
										er.BaseStream.Position -= 1;
										ssev.Add(new SSEQ.SSEQEvent(nr, er.ReadBytes(1)));
									}
									break;
								case 0xC6:
									er.ReadByte();
									if (loop == false)
									{
										er.BaseStream.Position -= 1;
										ssev.Add(new SSEQ.SSEQEvent(nr, er.ReadBytes(1)));
										treeView1.Nodes[curtrack].Nodes.Add("Priority");
									}
									break;
								case 0xC7:
									int mp = er.ReadByte();
									//mev[curtrack].Add(ControlChangeEvent.FromRawMessage(MidiMessage.ChangeControl(Convert.ToBoolean(mp) ? 126 : 127, 0, curtrack + 1).RawData));
									notewait = Convert.ToBoolean(mp);
									er.BaseStream.Position -= 1;
									ssev.Add(new SSEQ.SSEQEvent(nr, er.ReadBytes(1)));
									/*if (mp == 0)
									{
										//mev[curtrack].Add(new ControlChangeEvent(curtime, 1, 0x7F, 0));
										mev[curtrack].Add(ControlChangeEvent.FromRawMessage(MidiMessage.ChangeControl(0x7F, 0, curtrack).RawData));
										//z = new MidiEvent(outDevice, curtime, new ChannelMessage(ChannelCommand.Controller, curtrack, 0x7F, 0));
										//outDevice.Write(z);
									}
									else
									{
										mev[curtrack].Add(ControlChangeEvent.FromRawMessage(MidiMessage.ChangeControl(0x7E, nrtrack, curtrack).RawData));
									//outDevice.Send(new ChannelMessage(ChannelCommand.Controller, 0, 0x7E, nrtrack));
									}*/
									break;
								case 0xc8: /* Hanjuku Hero DS: NSE_42 */
									{
										int flg;
										flg = er.ReadByte();
										/* TODO: implement */
										if (loop == false)
										{
											treeView1.Nodes[curtrack].Nodes.Add("Tie");
											er.BaseStream.Position -= 1;
											ssev.Add(new SSEQ.SSEQEvent(nr, er.ReadBytes(1)));
										}
										//sprintf(eventName, "Tie"); 
										//sprintf(eventDesc, "%s (%d)", flg ? "On" : "Off", flg); 
										break;
									}
								case 0xC9:
									int pc = er.ReadByte();
									mev[0].Add(ControlChangeEvent.FromRawMessage(MidiMessage.ChangeControl(0x54, pc, realtrack).RawData));
									if (loop == false)
									{
										er.BaseStream.Position -= 1;
										ssev.Add(new SSEQ.SSEQEvent(nr, er.ReadBytes(1)));
										treeView1.Nodes[curtrack].Nodes.Add("Portamento Control");
									}
									break;

								case 0xCA:
									mev[curtrack].Add(new ControlChangeEvent(curtime, realtrack, MidiController.Modulation, er.ReadByte()));
									if (loop == false)
									{
										er.BaseStream.Position -= 1;
										ssev.Add(new SSEQ.SSEQEvent(nr, er.ReadBytes(1)));
										treeView1.Nodes[curtrack].Nodes.Add("Modulation Depth");
									}
									//z = new MidiEvent(outDevice, curtime, new ChannelMessage(ChannelCommand.Controller, curtrack, 0x01, er.ReadByte()));
									//outDevice.Write(z);
									break;
								case 0xcb: /* Dawn of Sorrow: SDL_BGM_ARR1_ */
									{
										int amount;

										amount = er.ReadByte();

										mev[curtrack].Add(ControlChangeEvent.FromRawMessage(MidiMessage.ChangeControl(76, 64 + amount / 2, realtrack).RawData));

										if (loop == false)
										{
											er.BaseStream.Position -= 1;
											ssev.Add(new SSEQ.SSEQEvent(nr, er.ReadBytes(1)));
											treeView1.Nodes[curtrack].Nodes.Add("Modulation Speed");
										}
										break;
									}
								case 0xCC:
									{
										string[] typeStr = { "Pitch", "Volume", "Pan" };
										int type = er.ReadByte();
										//mev[curtrack].Add(new ControlChangeEvent(curtime, realtrack, MidiController.Pan, pan));
										if (loop == false)
										{
											treeView1.Nodes[curtrack].Nodes.Add("Modulation Type: " + typeStr[type & 3]);
											er.BaseStream.Position -= 1;
											ssev.Add(new SSEQ.SSEQEvent(nr, er.ReadBytes(1)));
										}
										break;
									}
								case 0xcd:
									mev[curtrack].Add(ControlChangeEvent.FromRawMessage(MidiMessage.ChangeControl(77, 64 + er.ReadByte() / 2, realtrack).RawData));
									if (loop == false)
									{
										er.BaseStream.Position -= 1;
										ssev.Add(new SSEQ.SSEQEvent(nr, er.ReadBytes(1)));
										treeView1.Nodes[curtrack].Nodes.Add("Modulation Range");
									}
									break;
								case 0xCE:
									int po = er.ReadByte();
									mev[0].Add(ControlChangeEvent.FromRawMessage(MidiMessage.ChangeControl(0x41, po, realtrack).RawData));
									if (loop == false)
									{
										er.BaseStream.Position -= 1;
										ssev.Add(new SSEQ.SSEQEvent(nr, er.ReadBytes(1)));
										treeView1.Nodes[curtrack].Nodes.Add("Portamento");
									}
									break;
								case 0xCF:
									int pt = er.ReadByte();
									mev[0].Add(ControlChangeEvent.FromRawMessage(MidiMessage.ChangeControl(0x05, pt, realtrack).RawData));
									if (loop == false)
									{
										er.BaseStream.Position -= 1;
										ssev.Add(new SSEQ.SSEQEvent(nr, er.ReadBytes(1)));
										treeView1.Nodes[curtrack].Nodes.Add("Portamento Time");
									}
									break;
								case 0xD0:
									mev[curtrack].Add(ControlChangeEvent.FromRawMessage(MidiMessage.ChangeControl(0x49, 64 + er.ReadByte() / 2, realtrack).RawData));
									if (loop == false)
									{
										er.BaseStream.Position -= 1;
										ssev.Add(new SSEQ.SSEQEvent(nr, er.ReadBytes(1)));
										treeView1.Nodes[curtrack].Nodes.Add("Attack Rate");
									}
									break;
								case 0xD1:
									mev[curtrack].Add(ControlChangeEvent.FromRawMessage(MidiMessage.ChangeControl(0x4B, 64 + er.ReadByte() / 2, realtrack).RawData));
									if (loop == false)
									{
										er.BaseStream.Position -= 1;
										ssev.Add(new SSEQ.SSEQEvent(nr, er.ReadBytes(1)));
										treeView1.Nodes[curtrack].Nodes.Add("Decay Rate");
									}
									break;
								case 0xd2: /* Dawn of Sorrow: SDL_BGM_WIND_ */
									{
										int amount;

										amount = er.ReadByte();

										if (loop == false)
										{
											er.BaseStream.Position -= 1;
											ssev.Add(new SSEQ.SSEQEvent(nr, er.ReadBytes(1)));
											treeView1.Nodes[curtrack].Nodes.Add("Sustain Rate");
										}
										break;
									}
								case 0xD3:
									mev[curtrack].Add(ControlChangeEvent.FromRawMessage(MidiMessage.ChangeControl(0x48, 64 + er.ReadByte() / 2, realtrack).RawData));
									if (loop == false)
									{
										er.BaseStream.Position -= 1;
										ssev.Add(new SSEQ.SSEQEvent(nr, er.ReadBytes(1)));
										treeView1.Nodes[curtrack].Nodes.Add("Release Rate");
									}
									break;
								case 0xD4:
									{
										nrloop = er.ReadByte();
										mev[curtrack].Add(new TextEvent("loopStart", MetaEventType.Marker, curtime));
										if (loop == false)
										{
											er.BaseStream.Position -= 1;
											ssev.Add(new SSEQ.SSEQEvent(nr, er.ReadBytes(1)));
											treeView1.Nodes[curtrack].Nodes.Add("Loop Start Marker");
										}
										/*if (loopstart == -1)
										{
											loopstart = curtime;
										}*/
										break;
									}
								case 0xd5:
									mev[curtrack].Add(ControlChangeEvent.FromRawMessage(MidiMessage.ChangeControl(11, er.ReadByte(), realtrack).RawData));
									if (loop == false)
									{
										er.BaseStream.Position -= 1;
										ssev.Add(new SSEQ.SSEQEvent(nr, er.ReadBytes(1)));
										treeView1.Nodes[curtrack].Nodes.Add("Expression");
									}
									break;
								case 0xd6:
									er.ReadByte();
									if (loop == false)
									{
										er.BaseStream.Position -= 1;
										ssev.Add(new SSEQ.SSEQEvent(nr, er.ReadBytes(1)));
										treeView1.Nodes[curtrack].Nodes.Add("Print Variable");
									}
									break;
								case 0xE0:
									mev[curtrack].Add(ControlChangeEvent.FromRawMessage(MidiMessage.ChangeControl(0x4E, 64 + er.ReadInt16() / 2, realtrack).RawData));
									if (loop == false)
									{
										treeView1.Nodes[curtrack].Nodes.Add("Modulation Delay");
										//treeView1.Nodes[curtrack].Nodes[treeView1.Nodes[curtrack].Nodes.Count - 1].ImageIndex = 3;
										//treeView1.Nodes[curtrack].Nodes[treeView1.Nodes[curtrack].Nodes.Count - 1].SelectedImageIndex = 3;
										er.BaseStream.Position -= 2;
										ssev.Add(new SSEQ.SSEQEvent(nr, er.ReadBytes(2)));
									}
									break;
								case 0xE1:
									byte[] qw = er.ReadBytes(2);
									Array.Reverse(qw);
									bpm = int.Parse(BitConverter.ToString(qw).Replace("-", ""), System.Globalization.NumberStyles.HexNumber);
									mev[curtrack].Add(new TempoEvent((int)((60000000d / (double)bpm)), curtime));
									if (loop == false)
									{
										treeView1.Nodes[curtrack].Nodes.Add("Tempo (" + bpm + " bpm)");
										treeView1.Nodes[curtrack].Nodes[treeView1.Nodes[curtrack].Nodes.Count - 1].ImageIndex = 3;
										treeView1.Nodes[curtrack].Nodes[treeView1.Nodes[curtrack].Nodes.Count - 1].SelectedImageIndex = 3;
										er.BaseStream.Position -= 2;
										ssev.Add(new SSEQ.SSEQEvent(nr, er.ReadBytes(2)));
									}
									break;

								case 0xE3:
									mev[curtrack].Add(ControlChangeEvent.FromRawMessage(MidiMessage.ChangeControl(0x4E, 64 + er.ReadInt16() / 2, realtrack).RawData));
									if (loop == false)
									{
										treeView1.Nodes[curtrack].Nodes.Add("Sweep Pitch");
										//treeView1.Nodes[curtrack].Nodes[treeView1.Nodes[curtrack].Nodes.Count - 1].ImageIndex = 3;
										//treeView1.Nodes[curtrack].Nodes[treeView1.Nodes[curtrack].Nodes.Count - 1].SelectedImageIndex = 3;
										er.BaseStream.Position -= 2;
										ssev.Add(new SSEQ.SSEQEvent(nr, er.ReadBytes(2)));
									}
									break;
								case 0xFC:
									{
										mev[curtrack].Add(new TextEvent("loopEnd", MetaEventType.Marker, curtime));
										if (loop == false)
										{
											ssev.Add(new SSEQ.SSEQEvent(nr, null));
											treeView1.Nodes[curtrack].Nodes.Add("Loop End Marker");
										}
										/*if (loopend == -1)
										{
											loopend = curtime;
										}*/
										break;
									}
								case 0xFD:
									//er.BaseStream.Position = returnoffset;
									/*if (er.ReadByte() == 0xC7)
									{
										treeView1.Nodes[curtrack].Nodes.Add("End of Track");
										mev[curtrack].Add(new MetaEvent(MetaEventType.EndTrack, 0, curtime));
										curtrack += 1;
										curtime = 0;
									}
									er.BaseStream.Position -= 1;*/
									if (loop == false)
									{
										treeView1.Nodes[curtrack].Nodes.Add("Return");
										ssev.Add(new SSEQ.SSEQEvent(nr, null));
									}
									if (returnoffset != -1)
									{
										er.BaseStream.Seek(returnoffset, SeekOrigin.Begin);
										loop = false;
										returnoffset = -1;
									}
									break;
								case 0xFE:
									er.ReadInt16();
									if (loop == false)
									{
										er.BaseStream.Position -= 2;
										ssev.Add(new SSEQ.SSEQEvent(nr, er.ReadBytes(2)));
										treeView1.Nodes.Add("Multitrack");
									}
									break;
								case 0xFF:
									{
										mev[curtrack].Add(new MetaEvent(MetaEventType.EndTrack, 0, lasttime));
										treeView1.Nodes[curtrack].Nodes.Add("End of Track");
										/*for (int i = 0; i < mev[curtrack].Count - 1; i++)
										{
											if (mev[curtrack][i].DeltaTime == mev[curtrack][i + 1].DeltaTime && mev[curtrack][i] is NoteOnEvent && mev[curtrack][i + 1] is PitchWheelChangeEvent)
											{
												MidiEvent one = mev[curtrack][i];
												TreeNode n1 = treeView1.Nodes[curtrack].Nodes[i];
												MidiEvent two = mev[curtrack][i + 1];
												TreeNode n2 = treeView1.Nodes[curtrack].Nodes[i+1];
												mev[curtrack][i] = two;
												mev[curtrack][i + 1] = one;
												treeView1.Nodes[curtrack].Nodes[i] = n2;
												treeView1.Nodes[curtrack].Nodes[i + 1] = n1;
											}
										}*/
										ssev.Add(new SSEQ.SSEQEvent(nr, null));
										SSEQ.SSEQEvent[] s = new SSEQ.SSEQEvent[ssev.Count];
										ssev.CopyTo(s);
										tracks.Add(s.ToList());
										ssev.Clear();
										/*   if (er.ReadByte() == 0xC7)
										   {
											   treeView1.Nodes[curtrack].Nodes.Add("End of Track");
											   mev[curtrack].Add(new MetaEvent(MetaEventType.EndTrack, 0, curtime));
											   ssev.Add(new SSEQ.SSEQEvent(nr, null));
											   SSEQ.SSEQEvent[] s = new SSEQ.SSEQEvent[ssev.Count];
											   ssev.CopyTo(s);
											   tracks.Add(s.ToList());
											   ssev.Clear();
											   curtrack += 1;
											   curtime = 0;
										   }
										   else if (nrtrack == curtrack)
										   {
											   treeView1.Nodes[curtrack].Nodes.Add("End of Track");
											   mev[curtrack].Add(new MetaEvent(MetaEventType.EndTrack, 0, curtime));
											   ssev.Add(new SSEQ.SSEQEvent(nr, null));
											   SSEQ.SSEQEvent[] s = new SSEQ.SSEQEvent[ssev.Count];
											   ssev.CopyTo(s);
											   tracks.Add(s.ToList());
											   ssev.Clear();
											   goto end;
										   }*/
										//er.BaseStream.Position -= 1;
										if (nrtrack == curtrack)
										{
											goto end;
										}
										if (nrtrack != curtrack)
										{
											er.BaseStream.Position = offset[curtrack] + (ssar ? 0 : 0x1C);
											mev.AddTrack();
											curtrack += 1;
											realtrack += 1;
											if (realtrack == 11)
											{
												realtrack = lasttrack;
											}
											lasttime = 0;
											if (realtrack == 10)
											{
												realtrack++;
											}
											//if (realtrack == 17)
											//{
											//	realtrack = 1;
											//}
											vars = new short[255];
											curtime = 0;
											checkedListBox1.Items.Add("Track " + (curtrack + 1).ToString(), true);
											treeView1.Nodes.Insert(curtrack, "Track " + (curtrack + 1).ToString());
											treeView1.Nodes[curtrack].SelectedImageIndex = 1;
											treeView1.Nodes[curtrack].ImageIndex = 1;
										}
										break;
									}
								default:
									er.ReadByte();
									if (loop == false)
									{
										er.BaseStream.Position -= 1;
										byte[] by = er.ReadBytes(1);
										ssev.Add(new SSEQ.SSEQEvent(nr, by));
										treeView1.Nodes[curtrack].Nodes.Add("Undefined");
										MessageBox.Show("Undefined\nID: " + BitConverter.ToString(new byte[] { nr }).Replace("-", ""));
									}
									break;

							}
							lastevent = nr;
							if (excutestatement && lastevent != 0xa2)
							{
								excutestatement = false;
							}
						}
					}
				end:
					//mev.PrepareForExport();
					er.Dispose();
					er.Close();
				}
				else
				{
					MessageBox.Show("Error");
					er.Dispose();
					er.Close();
				}
			}
			else
			{
				MessageBox.Show("Error");
				er.Dispose();
				er.Close();
			}
		}
		public static int DecodeInt32(EndianBinaryReader reader)
		{
			if (reader == null)
				throw new ArgumentNullException("reader");

			bool more = true;
			int value = 0;
			int shift = 0;
			while (more)
			{
				byte lower7bits = reader.ReadByte();
				more = (lower7bits & 128) != 0;
				value |= (lower7bits & 0x7f) << shift;
				shift += 7;
			}
			return value;
		}
		int smfReadVarLength(EndianBinaryReader er)
		{
			int value;
			byte b = er.ReadByte();
			value = b & 0x7f;
			while ((er.BaseStream.Position < er.BaseStream.Length) && (b & 0x80) != 0)
			{
				value = value << 7;
				b = er.ReadByte();
				value |= b & 0x7f;
			}
			return value;
		}
		int smfWriteVarLength(int value, EndianBinaryWriter ew)
		{
			int transferedSize = 0;
			int varLengthSize = smfGetVarLengthSize(value);
			int sizeToTransfer = varLengthSize;

			if (sizeToTransfer != null)
			{
				int shiftCount = (varLengthSize - 1) * 7;

				for (transferedSize = 0; transferedSize < (sizeToTransfer - 1); transferedSize++)
				{
					ew.Write((byte)((byte)((value >> shiftCount) & 0x7f) | 0x80));
					shiftCount -= 7;
				}
				ew.Write((byte)((byte)((value >> shiftCount) & 0x7f)));
				transferedSize++;
			}
			return transferedSize;
		}
		int smfGetVarLengthSize(int value)
		{
			int varLengthSize = 1;
			int leftValue = value;

			while ((leftValue > 0x7f) && (varLengthSize < 4))
			{
				varLengthSize++;
				leftValue = leftValue >> 7;
			}
			return varLengthSize;
		}

		private void sseq_FormClosed(object sender, FormClosedEventArgs e)
		{

		}

		private void sseq_FormClosing(object sender, FormClosingEventArgs e)
		{
			//p.Stop();
			//p.Cancel();
			//p.Open("");
			//p = null;
			//if (CAPathPerformance != null)
			//{
			//CAPathPerformance.StopAll();
			//CAPathPerformance.ReleasePerformance();
			//}
			/*if (CSegment1 != null)
			{
				CSegment1.ReleaseSegment();
				CSegment1.UnloadAllPerformances();
				CSegment1.Dispose();
			}
			//CCollectionA.Dispose();
			if (CLoader != null)
			{
				//for(int i = 0; i < )
				//{

				//}
				CLoader.UnloadCollection(CCollectionA);
			}
			//CPortPerformance.RemovePort();
			COutPort.ReleasePort();
			CAPathPerformance.ReleasePerformance();
			CSegment1 = null;
			CLoader = null;
			CCollectionA = null;
			//CDMusic = null;
			//COutPort = null;
			//CAPathPerformance = null;
			this.Dispose();*/
			/*if (CAPathPerformance != null)
			{
				CAPathPerformance.StopAll();
			}
			CSegment1.ReleaseSegment();
			CSegment1.UnloadAllPerformances();
			CLoader.UnloadCollection(CCollectionA);*/
			m.Stop();
			m.Unload();
			if (File.Exists(midi))
			{
				File.Delete(midi);
			}
			if (File.Exists(dlss))
			{
				bool done;
				do
				{
					try
					{
						File.Delete(dlss);
						done = true;
					}
					catch
					{
						done = false;
						//t.Abort();
					}
				}
				while (!done);
			}
		}
		bool first = true;
		//MediaPlayer.MediaPlayer p = new MediaPlayer.MediaPlayer();
		/*DirectMidi.CDirectMusic CDMusic = new DirectMidi.CDirectMusic();
		DirectMidi.CDLSLoader CLoader = new DirectMidi.CDLSLoader();
		DirectMidi.COutputPort COutPort = new DirectMidi.COutputPort();
		//DirectMidi.CInputPort CInPort = new DirectMidi.CInputPort();
		//DirectMidi.CPortPerformance CPortPerformance = new DirectMidi.CPortPerformance();
		DirectMidi.CAPathPerformance CAPathPerformance = new DirectMidi.CAPathPerformance();
		DirectMidi.CCollection CCollectionA = new DirectMidi.CCollection();
		//DirectMidi.CInstrument CInstrument1 = new DirectMidi.CInstrument();
		//DirectMidi.CAudioPath CAudioPath1 = new DirectMidi.CAudioPath();
		DirectMidi.CSegment CSegment1 = new DirectMidi.CSegment();*/
		//DirectMidi.C3DSegment C3DSegment1 = new DirectMidi.C3DSegment();
		//DirectMidi.C3DBuffer C3DBuffer1 = new DirectMidi.C3DBuffer();
		string midi = "";
		string dlss = "";
		private void toolStripButton1_Click(object sender, EventArgs e)
		{
			/*if (!first)
			{
				//CCollectionA.Dispose();
				if (CAPathPerformance != null)
				{
					CAPathPerformance.Stop(CSegment1);
				}
				CSegment1.ReleaseSegment();
				CSegment1.UnloadAllPerformances();
				CLoader.UnloadCollection(CCollectionA);
				//CLoader.LoadDLS(null, out CCollectionA);
				//CLoader.Dispose();
				//CCollectionA.Dispose();
			}*/
			MidiEventCollection me = new MidiEventCollection(1, 48);
			for (int i = 0; i < mev.Tracks; i++)
			{
				if (checkedListBox1.GetItemChecked(i))
				{
					me.AddTrack(mev[i]);
				}
			}
			/*if (_channel != null)
			{
				_channel.stop();
				_channel = null;
			}
			if (_fmod != null)
			{
				_fmod.release();
				_fmod.close();
				_fmod = null;
				_sound = null;
			}*/
			if (first)
			{
				me.PrepareForExport();
				midi = Path.GetTempFileName();
				MidiFile.Export(midi, me);
			}
			if (first)
			{
				if (dls != null)
				{
					dlss = Path.GetTempFileName();
					//File.Create("C:\\tmp.dls").Close();
					File.WriteAllBytes(dlss, dls);
				}
			}

			/*var file = File.ReadAllBytes("C:\\tmp.mid");

			_fmod = new FMOD.System();
			FMOD.Factory.System_Create(ref _fmod);

			var result = _fmod.init(me.Tracks + 1, FMOD.INITFLAGS.NORMAL, (IntPtr)null);
			if (result != FMOD.RESULT.OK) return;//throw new Exception(FMOD.Error.String(result)); return;

			var info = new FMOD.CREATESOUNDEXINFO();
			info.cbsize = Marshal.SizeOf(info);
			//info.dlsname = "C:\\tmp.dls";
			//info.maxpolyphony = 64;
			info.length = (uint)file.Length;
			try
			{
				result = _fmod.createStream(file, FMOD.MODE.CREATESTREAM | FMOD.MODE.OPENMEMORY /*| FMOD.MODE.SOFTWARE, ref info, ref _sound);
			}
			catch
			{
				if (result != FMOD.RESULT.OK) return;//throw new Exception(FMOD.Error.String(result)); return;
			}
			_fmod.playSound(FMOD.CHANNELINDEX.FREE, _sound, false, ref _channel);*/

			//Microsoft.DirectX.AudioVideoPlayback.Audio a = Microsoft.DirectX.AudioVideoPlayback.Audio.FromFile("C:\\tmp.mid");
			//a.Play();
			/////////////////////////////// INITIALIZATION //////////////////////////





			///////////////////////// PLAYING A SEGMENT ////////



			// Loads a MIDI file into the segment
			//if (first)
			// {
			m.SetMidi(midi);
			//}
			//CLoader.LoadSegment("C:\\tmp.mid", out CSegment1, true);
			//int length = -1;
			//CSegment1.GetLength(out length);
			//double tempo = (me[0][0] as TempoEvent).Tempo / 4d;
			//tempo += 0.3;


			/*if (loopstart != -1 && loopend != -1)
			{
				int loopstart2 = (int)((6000 * (loopstart + 64)) / ((me[0][0] as TempoEvent).Tempo * 4));
				int loopend2 = (int)((6000 * (loopend + 64)) / ((me[0][0] as TempoEvent).Tempo * 4));
				CSegment1.SetLoopPoints((int)(loopstart2), (int)(loopend2+loopstart2));
			}*/
			if (first)
			{
				if (dls != null)
				{
					//CLoader.LoadDLS("C:\\tmp.dls", out CCollectionA);
					m.SetDLS(dlss);
					//CLoader.LoadDLSFromMem(dls, out CCollectionA);
				}
			}
			if (loopstart != -1 && loopend != -1 && first)
			{
				//CSegment1.SetRepeats(DirectMidi.DMUS_SEG.REPEAT_INFINITE);
				int le = m.GetLength();
				//double nr = (double)le / (double)(mev[0].Last().AbsoluteTime);
				int loops = (int)(loopstart * 16);//loopstart / 48 * (me[0][0] as TempoEvent).MicrosecondsPerQuarterNote / 693;
				int loope = (int)(loopend * 16);//loopend / 48 * (me[0][0] as TempoEvent).MicrosecondsPerQuarterNote / 693;
				//int loops = (int)((me[0][0] as TempoEvent).Tempo * 48 / 600000) * loopstart;
				//int loope = (int)((me[0][0] as TempoEvent).Tempo * 48 / 600000) * loopend;
				if (loops > le || loope > le || loope < loops) { goto cont; }
				else
				{
					//loope += loops;
					m.SetLoop(loops, loope, nrloop);
				}
			}
		cont:

			//CLoader.LoadSegment("C:\\tmp.mid", out CSegment1, true);

			// Repeats the segment ad infinitum
			if (loopstart != -1 && loopend != -1)
			{
				//CSegment1.SetRepeats(DirectMidi.DMUS_SEG.REPEAT_INFINITE);
			}

			// Downloads the segment to the performance
			/*if (dls != null)
			{
				CSegment1.ConnectToDLS(CCollectionA);
			}
			CSegment1.Download(CAPathPerformance);
            
			// Plays the segment

			//CPortPerformance.PlaySegment(CSegment1);
			//cout << "Playing a segment with the port performance." 
			//  "Press a key to continue...\n" << endl;



			// Stops the playing segment
			//CPortPerformance.Stop(CSegment1);


			// Downloads the segment to the audiopath performance

			//CSegment1.Download(CAPathPerformance);

			// Plays the segment in the performance
            
			CAPathPerformance.PlaySegment(CSegment1, null);*/
			if (first) { first = false; }
			m.Play();

			//cout << "Playing a segment with the audiopath performance." 
			//  " Press a key to continue...\n" << endl;

			//getch();

			// Stops the current playing segment

			//CAPathPerformance.Stop(CSegment1);


			//p.Open("C:\\tmp.mid");
			//p.Play();
		}
		private void toolStripButton2_Click(object sender, EventArgs e)
		{
			if (MessageBox.Show("Do you want to export all channels?", "Export", MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.No)
			{
				MidiEventCollection me = new MidiEventCollection(1, 48);
				for (int i = 0; i < mev.Tracks; i++)
				{
					if (checkedListBox1.GetItemChecked(i))
					{
						me.AddTrack(mev[i]);
					}
				}
				if (saveFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK
					&& saveFileDialog1.FileName.Length > 0)
				{
					MidiFile.Export(saveFileDialog1.FileName, me);
				}
			}
			else
			{
				if (name != null)
				{
					saveFileDialog1.FileName = name.Replace(".sseq", ".mid").Replace(".SSEQ", ".mid");
				}
				if (saveFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK
					&& saveFileDialog1.FileName.Length > 0)
				{
					MidiFile.Export(saveFileDialog1.FileName, mev);
				}
			}
		}

		private void toolStripButton3_Click(object sender, EventArgs e)
		{
			//p.Stop();
			//p.Cancel();
			//p.Open("");
			//CAPathPerformance.Stop(CSegment1);
			m.Stop();
		}

		public void midiToSSEQ(string infile, string outfile)
		{
			MidiFile f = new MidiFile(infile);
			EndianBinaryWriter ew = new EndianBinaryWriter(File.OpenWrite(outfile), Endianness.LittleEndian);
			List<SSEQ.SSEQEvent>[] midiTracks = new List<SSEQ.SSEQEvent>[(f.Tracks > 16 ? 15 : f.Tracks)];
			List<long>[] deltas = new List<long>[(f.Tracks > 15 ? 16 : f.Tracks)];
			for (int i = 0; i < (f.Tracks > 16 ? 15 : f.Tracks); i++)
			{
				midiTracks[i] = new List<SSEQ.SSEQEvent>();
				deltas[i] = new List<long>();
			}
			int trackpos = 0;
			int tpb = f.DeltaTicksPerQuarterNote;
			byte[] tracksUsed = new byte[2];
			midiTracks[0].Add(new SSEQ.SSEQEvent(0xFE, tracksUsed));
			for (int i = 0; i < (f.Tracks > 16 ? 15 : f.Tracks); i++)
			{
				byte[] var = new byte[4];
				var[0] = (byte)i;
				midiTracks[0].Add(new SSEQ.SSEQEvent(0x93, var));
			}
			int looplength = 0;
			bool loopstartset = false;
			int tempo = 0;
			for (int i = 0; i < (f.Tracks > 16 ? 15 : f.Tracks); i++)
			{
				byte[] off = GetInt24(trackpos);
				midiTracks[0][i + 1].Params[1] = off[0];
				midiTracks[0][i + 1].Params[2] = off[1];
				midiTracks[0][i + 1].Params[3] = off[2];
				//int lasttime = 0;
				midiTracks[i].Add(new SSEQ.SSEQEvent(0xC7, new byte[] { 0x00 }));
				trackpos += 2;
				if (tempo != 0)
				{
					midiTracks[i].Add(new SSEQ.SSEQEvent(0xE1, GetInt16(tempo)));
					trackpos += 3;
				}
				int dataentry = 0;
				trackpos += looplength;
				for (int j = 0; j < f.Events[i].Count; j++)
				{
					int delta = (int)f.Events[i][j].DeltaTime;
					if (delta != 0 && (f.Events[i][j] is NoteOnEvent || f.Events[i][j] is PatchChangeEvent || f.Events[i][j] is TempoEvent))
					{
						byte[] b = new byte[smfGetVarLengthSize(delta)];
						EndianBinaryWriter w = new EndianBinaryWriter(new MemoryStream(b));
						smfWriteVarLength(delta, w);
						w.Close();
						midiTracks[i].Add(new SSEQ.SSEQEvent(0x80, b));
						trackpos += b.Length + 1;
					}
					//lasttime = (int)f.Events[i][j].AbsoluteTime;
					switch (f.Events[i][j].CommandCode)
					{
						case MidiCommandCode.NoteOn:
							{
								NoteOnEvent e = (NoteOnEvent)f.Events[i][j];
								byte[] b = new byte[smfGetVarLengthSize(e.NoteLength) + 1];
								EndianBinaryWriter w = new EndianBinaryWriter(new MemoryStream(b));
								w.Write((byte)e.Velocity);
								smfWriteVarLength(e.NoteLength, w);
								w.Close();
								midiTracks[i].Add(new SSEQ.SSEQEvent(e.NoteNumber, b));
								trackpos += b.Length + 1;
								break;
							}
						case MidiCommandCode.PatchChange:
							{
								PatchChangeEvent e = (PatchChangeEvent)f.Events[i][j];
								midiTracks[i].Add(new SSEQ.SSEQEvent(0x81, new byte[] { (byte)(e.Patch & 0x7F) }));
								trackpos += 2;
								break;
							}
						case MidiCommandCode.PitchWheelChange:
							{
								PitchWheelChangeEvent e = (PitchWheelChangeEvent)f.Events[i][j];
								midiTracks[i].Add(new SSEQ.SSEQEvent(0xC4, new byte[] { (byte)(e.Pitch & 0xFF) }));
								trackpos += 2;
								break;
							}
						case MidiCommandCode.MetaEvent:
							{
								MetaEvent e1 = (MetaEvent)f.Events[i][j];
								switch (e1.MetaEventType)
								{
									case MetaEventType.SetTempo:
										{
											TempoEvent e = (TempoEvent)f.Events[i][j];
											//for (int k = 0; k < midiTracks.Length; k++)
											//{
											midiTracks[i].Add(new SSEQ.SSEQEvent(0xE1, GetInt16((int)e.Tempo)));
											if (tempo == 0)
											{
												tempo = (int)e.Tempo;
											}
											//}
											trackpos += 3;
											break;
										}
									case MetaEventType.EndTrack:
										{
											midiTracks[i].Add(new SSEQ.SSEQEvent(0xFF, null));
											trackpos++;
											break;
										}
									case MetaEventType.Marker:
										{
											NAudio.Midi.TextEvent e = (TextEvent)f.Events[i][j];
											if (e.Text == "loopStart")
											{
												//for (int k = 0; k < midiTracks.Length; k++)
												//{
												midiTracks[i].Add(new SSEQ.SSEQEvent(0x00, new byte[] { 0x6C, 0x6F, 0x6F, 0x70, 0x53, 0x74, 0x61, 0x72, 0x74 }));
												//}
											}
											else if (e.Text == "loopEnd" && loopstartset)
											{
												//for (int k = 0; k < midiTracks.Length; k++)
												// {
												midiTracks[i].Add(new SSEQ.SSEQEvent(0x94, new byte[] { 0x6C, 0x6F, 0x6F, 0x70, 0x45, 0x6E, 0x64 }));
												//}
												trackpos += 4;
												//looplength += 4;
											}
											break;
										}
								}
								break;
							}
						case MidiCommandCode.ControlChange:
							{
								ControlChangeEvent e = (ControlChangeEvent)f.Events[i][j];
								switch (e.Controller)
								{
									case MidiController.MainVolume:
										midiTracks[i].Add(new SSEQ.SSEQEvent(0xC1, new byte[] { (byte)(e.ControllerValue & 0x7F) }));
										trackpos += 2;
										break;
									case MidiController.Pan:
										midiTracks[i].Add(new SSEQ.SSEQEvent(0xC0, new byte[] { (byte)(e.ControllerValue & 0x7F) }));
										trackpos += 2;
										break;
									case MidiController.Modulation:
										midiTracks[i].Add(new SSEQ.SSEQEvent(0xCA, new byte[] { (byte)(e.ControllerValue) }));
										trackpos += 2;
										break;
									default:
										switch ((int)e.Controller)
										{
											case 6:
												if (dataentry == 0)
												{
													midiTracks[i].Add(new SSEQ.SSEQEvent(0xC5, new byte[] { (byte)(e.ControllerValue & 0x7F) }));
													trackpos += 2;
												}
												break;
											case 100:
												dataentry &= ~0x7F;
												dataentry |= (int)e.ControllerValue;
												break;
											case 101:
												dataentry &= ~(0x7F << 7);
												dataentry |= (int)e.ControllerValue << 7;
												break;
										}
										break;
								}
								break;
							}
					}
				}
			}
			ew.Write("SSEQ", Encoding.ASCII, false);
			ew.Write(new byte[] { 0xFF, 0xFE, 0x00, 0x01 }, 0, 4);
			ew.Write((Int32)0);
			ew.Write((Int16)16);
			ew.Write((Int16)1);
			//Data
			ew.Write("DATA", Encoding.ASCII, false);
			ew.Write((Int32)0);
			ew.Write((Int32)0x1C);
			int loopStart = 0;
			for (int i = 0; i < midiTracks.Length; i++)
			{
				for (int j = 0; j < midiTracks[i].Count; j++)
				{
					if (midiTracks[i][j].Params != new byte[] { 0x6C, 0x6F, 0x6F, 0x70, 0x53, 0x74, 0x61, 0x72, 0x74 } && midiTracks[i][j].Params != new byte[] { 0x6C, 0x6F, 0x6F, 0x70, 0x45, 0x6E, 0x64 })
					{
						ew.Write((byte)midiTracks[i][j].Type);
						if (midiTracks[i][j].Params != null)
						{
							ew.Write(midiTracks[i][j].Params, 0, midiTracks[i][j].Params.Length);
						}
					}
					else if (midiTracks[i][j].Params == new byte[] { 0x6C, 0x6F, 0x6F, 0x70, 0x53, 0x74, 0x61, 0x72, 0x74 })
					{
						loopStart = (int)ew.BaseStream.Position - 0x1c;
					}
					else
					{
						if (loopStart == 0)
						{
							MessageBox.Show("No loopStart marker set!");
						}
						else
						{
							ew.Write((byte)0x94);
							ew.Write(GetInt24(loopStart), 0, 3);
							//ew.Write((byte)0xFF);
							//break;
						}
					}
				}
			}
			long length = ew.BaseStream.Length;
			ew.BaseStream.Seek(8, SeekOrigin.Begin);
			ew.Write((Int32)length);
			ew.BaseStream.Seek(20, SeekOrigin.Begin);
			ew.Write((Int32)length - 16);
			ew.Close();
		}

		private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
		{
			if (treeView1.SelectedNode == null || treeView1.SelectedNode.Parent == null)
			{
				toolStripButton4.Enabled = false;
				toolStripButton5.Enabled = false;
			}
			else
			{
				toolStripButton4.Enabled = true;
				toolStripButton5.Enabled = true;
			}
		}

		private void treeView1_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
		{
			if (e.Node.Parent != null)
			{

			}
		}

		private void toolStripButton4_ButtonClick(object sender, EventArgs e)
		{

		}

		private void noteToolStripMenuItem_Click(object sender, EventArgs e)
		{
			if (treeView1.SelectedNode.Parent.Index == 0)
			{
				SSEQ.Note n = new SSEQ.Note();
				n.ShowDialog();
				byte[] b = new byte[smfGetVarLengthSize(n.duration) + 1];
				EndianBinaryWriter w = new EndianBinaryWriter(new MemoryStream(b));
				w.Write((byte)n.velocity);
				smfWriteVarLength(n.duration, w);
				w.Close();
				tracks[treeView1.SelectedNode.Parent.Index].Insert(treeView1.SelectedNode.Index + mev.Tracks + 1, new SSEQ.SSEQEvent(n.nr, b));
				treeView1.SelectedNode.Parent.Nodes.Insert(treeView1.SelectedNode.Index, "Note (" + n.nr.ToString() + ")");
				for (int i = 0; i < offs.Count; i++)
				{
					if (offs[i][0] == 0)
					{
						if (offs[i][1] + mev.Tracks + 1 >= treeView1.SelectedNode.Index + mev.Tracks + 1)
						{
							offs[i][3] += smfGetVarLengthSize(n.duration) + 2;
							tracks[0][offs[i][2]].Params = GetInt24(offs[i][3]);
						}
					}
					else
					{
						offs[i][3] += smfGetVarLengthSize(n.duration) + 2;
						tracks[offs[i][0]][offs[i][2]].Params = GetInt24(offs[i][3]);
					}
				}
			}
			else
			{
				SSEQ.Note n = new SSEQ.Note();
				n.ShowDialog();
				byte[] b = new byte[smfGetVarLengthSize(n.duration) + 1];
				EndianBinaryWriter w = new EndianBinaryWriter(new MemoryStream(b));
				w.Write((byte)n.velocity);
				smfWriteVarLength(n.duration, w);
				w.Close();
				tracks[treeView1.SelectedNode.Parent.Index].Insert(treeView1.SelectedNode.Index + 1, new SSEQ.SSEQEvent(n.nr, b));
				treeView1.SelectedNode.Parent.Nodes.Insert(treeView1.SelectedNode.Index, "Note (" + n.nr.ToString() + ")");
				for (int i = 0; i < offs.Count; i++)
				{
					if (offs[i][0] == treeView1.SelectedNode.Parent.Index)
					{
						if (offs[i][1] + 1 >= treeView1.SelectedNode.Index + 1)
						{
							offs[i][3] += smfGetVarLengthSize(n.duration) + 2;
							tracks[offs[i][0]][offs[i][2]].Params = GetInt24(offs[i][3]);
						}
					}
					else
					{
						offs[i][3] += smfGetVarLengthSize(n.duration) + 2;
						tracks[offs[i][0]][offs[i][2]].Params = GetInt24(offs[i][3]);
					}
				}
			}
		}

		public static byte[] GetInt24(int value)
		{
			byte[] buffer = new byte[3];
			buffer[0] = (byte)value;
			buffer[1] = (byte)(value >> 8);
			buffer[2] = (byte)(value >> 16);
			return buffer;
		}

		public static byte[] GetInt16(int value)
		{
			byte[] buffer = new byte[2];
			buffer[0] = (byte)value;
			buffer[1] = (byte)(value >> 8);
			return buffer;
		}


		private void toolStripButton5_Click(object sender, EventArgs e)
		{
			if (treeView1.SelectedNode.Parent.Index == 0)
			{
				/*for (int i = 0; i < offs.Count; i++)
				{
					if (offs[i][0] == 1 && offs[i][1] + 1 <= treeView1.SelectedNode.Index + 1)
					{
						offs[i][3] += smfGetVarLengthSize(n.duration) + 2;
						tracks[0][offs[i][2]].Params = GetInt24(offs[i][3]);
					}
				}*/
				tracks[treeView1.SelectedNode.Parent.Index].RemoveAt(treeView1.SelectedNode.Index + mev.Tracks + 1);
				treeView1.SelectedNode.Remove();
			}
			else
			{
				tracks[treeView1.SelectedNode.Parent.Index].RemoveAt(treeView1.SelectedNode.Index + 1);
				treeView1.SelectedNode.Remove();
			}
		}
		public byte[] getBytes()
		{
			if (buffer == null)
			{
				return file;
			}
			else
			{
				return buffer;
			}
		}

		private void toolStripButton6_Click(object sender, EventArgs e)
		{
			MemoryStream m = new MemoryStream();
			EndianBinaryWriter ew = new EndianBinaryWriter(m, Endianness.LittleEndian);
			ew.Write("SSEQ", Encoding.ASCII, false);
			ew.Write(new byte[] { 0xFF, 0xFE, 0x00, 0x01 }, 0, 4);
			ew.Write((Int32)0);
			ew.Write((Int16)16);
			ew.Write((Int16)1);
			//Data
			ew.Write("DATA", Encoding.ASCII, false);
			ew.Write((Int32)0);
			ew.Write((Int32)0x1C);
			for (int i = 0; i < tracks.Count; i++)
			{
				for (int j = 0; j < tracks[i].Count; j++)
				{
					ew.Write((byte)tracks[i][j].Type);
					if (tracks[i][j].Params != null)
					{
						ew.Write(tracks[i][j].Params, 0, tracks[i][j].Params.Length);
					}
				}
			}
			long length = ew.BaseStream.Length;
			ew.BaseStream.Seek(8, SeekOrigin.Begin);
			ew.Write((Int32)length);
			ew.BaseStream.Seek(20, SeekOrigin.Begin);
			ew.Write((Int32)length - 16);
			ew.Close();
			buffer = m.ToArray();
		}
		public static Sbnk readSBNK(byte[] file)
		{
			EndianBinaryReader er = new EndianBinaryReader(new MemoryStream(file), Endianness.LittleEndian);
			Sbnk s = new Sbnk();
			s.type = er.ReadString(Encoding.ASCII, 4);
			if (s.type == "SBNK")
			{
				s.magic = er.ReadBytes(4);
				s.nFileSize = er.ReadInt32();
				s.nSize = er.ReadInt16();
				s.nBlock = er.ReadInt16();
				s.Data.type = er.ReadString(Encoding.ASCII, 4);
				if (s.Data.type == "DATA")
				{
					s.Data.nSize = er.ReadInt32();
					s.Data.reserved = er.ReadInt32s(8);
					s.Data.nCount = er.ReadInt32();
					s.Data.Ins = new SbnkInstrument[s.Data.nCount];
					for (int i = 0; i < s.Data.nCount; i++)
					{
						s.Data.Ins[i].fRecord = er.ReadByte();
						s.Data.Ins[i].nOffset = er.ReadInt16();
						s.Data.Ins[i].reserved = er.ReadByte();
					}
					for (int i = 0; i < s.Data.nCount; i++)
					{
						long curpos = er.BaseStream.Position;
						er.BaseStream.Position = s.Data.Ins[i].nOffset;
						if (s.Data.Ins[i].fRecord == 0)
						{
							iRecord0 info = new iRecord0();
							s.Data.Ins[i].iInfo = info;
						}
						else if (s.Data.Ins[i].fRecord < 16)
						{
							iRecord_16 info = new iRecord_16();
							info.nrSwav = er.ReadInt16();
							info.nrSwar = er.ReadInt16();
							info.Note = er.ReadByte();
							info.AttackRate = er.ReadByte();
							info.DecayRate = er.ReadByte();
							info.SustainLevel = er.ReadByte();
							info.ReleaseRate = er.ReadByte();
							info.Pan = er.ReadByte();
							s.Data.Ins[i].iInfo = info;
						}
						else if (s.Data.Ins[i].fRecord == 16)
						{
							iRecord16 info = new iRecord16();
							info.lNote = er.ReadByte();
							info.uNote = er.ReadByte();
							int nr = info.uNote - info.lNote + 1;
							info.Info = new iRecord16.info[nr];
							for (int j = 0; j < nr; j++)
							{
								info.Info[j].Unknown = er.ReadBytes(2);
								info.Info[j].nrSwav = er.ReadInt16();
								info.Info[j].nrSwar = er.ReadInt16();
								info.Info[j].Note = er.ReadByte();
								info.Info[j].AttackRate = er.ReadByte();
								info.Info[j].DecayRate = er.ReadByte();
								info.Info[j].SustainLevel = er.ReadByte();
								info.Info[j].ReleaseRate = er.ReadByte();
								info.Info[j].Pan = er.ReadByte();
							}
							s.Data.Ins[i].iInfo = info;
						}
						else if (s.Data.Ins[i].fRecord == 17)
						{
							iRecord17 info = new iRecord17();
							info.Regions = new byte[8];
							for (int j = 0; j < 8; j++)
							{
								info.Regions[j] = er.ReadByte();
								if (info.nr == 0 && info.Regions[j] == 0)
								{
									info.nr = j;
								}
							}
							info.Info = new iRecord17.info[info.nr];
							for (int j = 0; j < info.nr; j++)
							{
								info.Info[j].Unknown = er.ReadBytes(2);
								info.Info[j].nrSwav = er.ReadInt16();
								info.Info[j].nrSwar = er.ReadInt16();
								info.Info[j].Note = er.ReadByte();
								info.Info[j].AttackRate = er.ReadByte();
								info.Info[j].DecayRate = er.ReadByte();
								info.Info[j].SustainLevel = er.ReadByte();
								info.Info[j].ReleaseRate = er.ReadByte();
								info.Info[j].Pan = er.ReadByte();
							}
							s.Data.Ins[i].iInfo = info;
						}
						er.BaseStream.Position = curpos;
					}
					er.Close();
				}
				else
				{
					MessageBox.Show("Error");
					er.Close();
				}
			}
			else
			{
				MessageBox.Show("Error");
				er.Close();
			}
			return s;
		}
		private static byte[] AttackTimeTable = { 0x00, 0x01, 0x05, 0x0E, 0x1A, 0x26,
		0x33, 0x3F, 0x49, 0x54, 0x5C, 0x64, 0x6D, 0x74, 0x7B, 0x7F, 0x84,
		0x89, 0x8F};

		private static ushort[] sustainLevTable = { 0xFD2D, 0xFD2E, 0xFD2F, 0xFD75, 0xFDA7, 0xFDCE, 0xFDEE, 0xFE09, 0xFE20, 0xFE34, 0xFE46, 0xFE57, 0xFE66, 0xFE74,
	0xFE81, 0xFE8D, 0xFE98, 0xFEA3, 0xFEAD, 0xFEB6, 0xFEBF, 0xFEC7, 0xFECF, 0xFED7, 0xFEDF, 0xFEE6, 0xFEEC, 0xFEF3,
	0xFEF9, 0xFEFF, 0xFF05, 0xFF0B, 0xFF11, 0xFF16, 0xFF1B, 0xFF20, 0xFF25, 0xFF2A, 0xFF2E, 0xFF33, 0xFF37, 0xFF3C,
	0xFF40, 0xFF44, 0xFF48, 0xFF4C, 0xFF50, 0xFF53, 0xFF57, 0xFF5B, 0xFF5E, 0xFF62, 0xFF65, 0xFF68, 0xFF6B, 0xFF6F,
	0xFF72, 0xFF75, 0xFF78, 0xFF7B, 0xFF7E, 0xFF81, 0xFF83, 0xFF86, 0xFF89, 0xFF8C, 0xFF8E, 0xFF91, 0xFF93, 0xFF96,
	0xFF99, 0xFF9B, 0xFF9D, 0xFFA0, 0xFFA2, 0xFFA5, 0xFFA7, 0xFFA9, 0xFFAB, 0xFFAE, 0xFFB0, 0xFFB2, 0xFFB4, 0xFFB6,
	0xFFB8, 0xFFBA, 0xFFBC, 0xFFBE, 0xFFC0, 0xFFC2, 0xFFC4, 0xFFC6, 0xFFC8, 0xFFCA, 0xFFCC, 0xFFCE, 0xFFCF, 0xFFD1,
	0xFFD3, 0xFFD5, 0xFFD6, 0xFFD8, 0xFFDA, 0xFFDC, 0xFFDD, 0xFFDF, 0xFFE1, 0xFFE2, 0xFFE4, 0xFFE5, 0xFFE7, 0xFFE9,
	0xFFEA, 0xFFEC, 0xFFED, 0xFFEF, 0xFFF0, 0xFFF2, 0xFFF3, 0xFFF5, 0xFFF6, 0xFFF8, 0xFFF9, 0xFFFA, 0xFFFC, 0xFFFD, 
	0xFFFF, 0x0000 };
		private static double INTR_FREQUENCY = (1.0 / 192.0);//0.005210332809750868
		public static Sbnk setWaves(Sbnk k, SDAT.SWAR.ArchivoSWAR[] waves)
		{
			Sbnk s = k;
			for (int i = 0; i < s.Data.nCount; i++)
			{
				short realDecay;
				short realRelease;
				byte realAttack;
				long realSustainLev;
				if (s.Data.Ins[i].fRecord == 0)
				{
					iRecord0 info = (iRecord0)s.Data.Ins[i].iInfo;
				}
				else if (s.Data.Ins[i].fRecord < 16)
				{
					iRecord_16 info = (iRecord_16)s.Data.Ins[i].iInfo;
					//if (!nrSwar.Contains(info.nrSwar))
					//{
					//    nrSwar.Add(info.nrSwar);
					// }
					info.WaveData = SDAT.SWAR.ConvertirASWAV(waves[info.nrSwar])[info.nrSwav];
					if (info.AttackRate >= 0x6D)
						realAttack = AttackTimeTable[0x7F - info.AttackRate];
					else
						realAttack = (byte)(0xFF - info.AttackRate);

					realDecay = (short)GetFallingRate(info.DecayRate);
					realRelease = (short)GetFallingRate(info.ReleaseRate);

					int count = 0;
					for (long j = 0x16980; j != 0; j = (j * realAttack) >> 8)
						count++;
					info.RealAttackRate = count * INTR_FREQUENCY;

					if (info.SustainLevel == 0x7F)
						realSustainLev = 0;
					else
						realSustainLev = (0x10000 - sustainLevTable[info.SustainLevel]) << 7;
					if (info.DecayRate == 0x7F)
						info.RealDecayRate = 0.001;
					else
					{
						count = 0x16980 / realDecay;//realSustainLev / realDecay;
						info.RealDecayRate = count * INTR_FREQUENCY;
					}

					//rgn->bSustainInPctVol = false;
					//rgn->bSustainInDecibel = true;

					if (realSustainLev == 0)
						info.RealSustainLevel = 1.0;
					else
					{
						//rgn->sustain_level = 20 * log10 ((92544.0-realSustainLev) / 92544.0);
						info.RealSustainLevel = (double)(0x16980 - realSustainLev) / (double)0x16980;
					}


					count = 0x16980 / realRelease;		//we express release rate as time from maximum volume, not sustain level
					info.RealReleaseRate = count * INTR_FREQUENCY;

					if (info.Pan == 0)
						info.RealPan = -1.0;
					else if (info.Pan == 0x7F)
						info.RealPan = 1.0;
					else if (info.Pan == 0x40)
						info.RealPan = 0;
					else
						info.RealPan = (double)(info.Pan - 63.5) / (double)0x40;

					if (info.RealReleaseRate < .001)
						info.RealReleaseRate = .001;
					if (info.RealDecayRate < .001)
						info.RealDecayRate = .001;
					if (info.RealAttackRate < .001)
						info.RealAttackRate = .001;

					long convAttack = (long)Math.Ceiling((Math.Log(info.RealAttackRate) / Math.Log((double)2)) * 1200 * 65536);
					long convDecay = (long)Math.Ceiling((Math.Log(info.RealDecayRate) / Math.Log((double)2)) * 1200 * 65536);
					long convSustainLev;
					convSustainLev = (long)(0x03e80000 * info.RealSustainLevel);//(long)((double)0x03e80000 * ((double)info.SustainLevel / (double)127));
					/*if (info.RealSustainLevel == -1)
						convSustainLev = 0x03e80000;		//sustain at full if no sustain level provided
					else if (true)
						convSustainLev = (long)(((96.0 + info.RealSustainLevel) / 96.0) * 0x03e80000);*/
					//the DLS envelope is a range from 0 to -96db. 

					//convSustainLev = (long)(vgmrgn->sustain_level*0x03e80000);
					long convRelease = (long)Math.Ceiling((Math.Log(info.RealReleaseRate) / Math.Log((double)2)) * 1200 * 65536);


					long pan = 0;
					//if (vgmrgn->bPanIn10thPctUnits)
					//	pan = vgmrgn->pan;
					//if (vgmrgn->pan != 0)	//by default pan is a double value between -1.0 and 1.0 (abs left and right)
					//	pan = (long)ceil((vgmrgn->pan*0x40) * 516031.49606299212598425196850394);
					if (info.RealPan != 0) //by default pan is a double value between -1.0 and 1.0 (abs left and right)
						pan = (long)((info.RealPan) * 32768000);

					info.RealPan = pan;
					info.RealAttackRate = convAttack;
					info.RealDecayRate = convDecay;
					info.RealReleaseRate = convRelease;
					info.RealSustainLevel = convSustainLev;


					s.Data.Ins[i].iInfo = info;
				}
				else if (s.Data.Ins[i].fRecord == 16)
				{
					iRecord16 info = (iRecord16)s.Data.Ins[i].iInfo;
					int nr = info.uNote - info.lNote + 1;
					for (int j = 0; j < nr; j++)
					{
						info.Info[j].WaveData = SDAT.SWAR.ConvertirASWAV(waves[info.Info[j].nrSwar])[info.Info[j].nrSwav];
						if (info.Info[j].AttackRate >= 0x6D)
							realAttack = AttackTimeTable[0x7F - info.Info[j].AttackRate];
						else
							realAttack = (byte)(0xFF - info.Info[j].AttackRate);

						realDecay = (short)GetFallingRate(info.Info[j].DecayRate);
						realRelease = (short)GetFallingRate(info.Info[j].ReleaseRate);

						int count = 0;
						for (long l = 0x16980; l != 0; l = (l * realAttack) >> 8)
							count++;
						info.Info[j].RealAttackRate = count * INTR_FREQUENCY;

						if (info.Info[j].SustainLevel == 0x7F)
							realSustainLev = 0;
						else
							realSustainLev = (0x10000 - sustainLevTable[info.Info[j].SustainLevel]) << 7;
						if (info.Info[j].DecayRate == 0x7F)
							info.Info[j].RealDecayRate = 0.001;
						else
						{
							count = 0x16980 / realDecay;//realSustainLev / realDecay;
							info.Info[j].RealDecayRate = count * INTR_FREQUENCY;
						}

						//rgn->bSustainInPctVol = false;
						//rgn->bSustainInDecibel = true;

						if (realSustainLev == 0)
							info.Info[j].RealSustainLevel = 1.0;
						else
						{
							//rgn->sustain_level = 20 * log10 ((92544.0-realSustainLev) / 92544.0);
							info.Info[j].RealSustainLevel = (double)(0x16980 - realSustainLev) / (double)0x16980;
						}


						count = 0x16980 / realRelease;		//we express release rate as time from maximum volume, not sustain level
						info.Info[j].RealReleaseRate = count * INTR_FREQUENCY;

						if (info.Info[j].Pan == 0)
							info.Info[j].RealPan = -1.0;
						else if (info.Info[j].Pan == 0x7F)
							info.Info[j].RealPan = 1.0;
						else if (info.Info[j].Pan == 0x40)
							info.Info[j].RealPan = 0;
						else
							info.Info[j].RealPan = (double)(info.Info[j].Pan - 63.5) / (double)0x40;


						if (info.Info[j].RealReleaseRate < .001)
							info.Info[j].RealReleaseRate = .001;
						if (info.Info[j].RealDecayRate < .001)
							info.Info[j].RealDecayRate = .001;
						if (info.Info[j].RealAttackRate < .001)
							info.Info[j].RealAttackRate = .001;

						long convAttack = (long)Math.Ceiling((Math.Log(info.Info[j].RealAttackRate) / Math.Log((double)2)) * 1200 * 65536);
						long convDecay = (long)Math.Ceiling((Math.Log(info.Info[j].RealDecayRate) / Math.Log((double)2)) * 1200 * 65536);
						long convSustainLev;
						/* if (info.Info[j].RealSustainLevel == -1)
							 convSustainLev = 0x03e80000;		//sustain at full if no sustain level provided
						 else if (true)
							 convSustainLev = (long)(((96.0 + info.Info[j].RealSustainLevel) / 96.0) * 0x03e80000);		//the DLS envelope is a range from 0 to -96db. 
						 */
						convSustainLev = (long)(0x03e80000 * info.Info[j].RealSustainLevel);
						//convSustainLev = (long)(vgmrgn->sustain_level*0x03e80000);
						long convRelease = (long)Math.Ceiling((Math.Log(info.Info[j].RealReleaseRate) / Math.Log((double)2)) * 1200 * 65536);


						long pan = 0;
						//if (vgmrgn->bPanIn10thPctUnits)
						//	pan = vgmrgn->pan;
						//if (vgmrgn->pan != 0)	//by default pan is a double value between -1.0 and 1.0 (abs left and right)
						//	pan = (long)ceil((vgmrgn->pan*0x40) * 516031.49606299212598425196850394);
						if (info.Info[j].RealPan != 0) //by default pan is a double value between -1.0 and 1.0 (abs left and right)
							pan = (long)((info.Info[j].RealPan) * 32768000);

						info.Info[j].RealPan = pan;
						info.Info[j].RealAttackRate = convAttack;
						info.Info[j].RealDecayRate = convDecay;
						info.Info[j].RealReleaseRate = convRelease;
						info.Info[j].RealSustainLevel = convSustainLev;
					}
					s.Data.Ins[i].iInfo = info;
				}
				else if (s.Data.Ins[i].fRecord == 17)
				{
					iRecord17 info = (iRecord17)s.Data.Ins[i].iInfo;
					for (int j = 0; j < info.nr; j++)
					{
						info.Info[j].WaveData = SDAT.SWAR.ConvertirASWAV(waves[info.Info[j].nrSwar])[info.Info[j].nrSwav];
						if (info.Info[j].AttackRate >= 0x6D)
							realAttack = AttackTimeTable[0x7F - info.Info[j].AttackRate];
						else
							realAttack = (byte)(0xFF - info.Info[j].AttackRate);

						realDecay = (short)GetFallingRate(info.Info[j].DecayRate);
						realRelease = (short)GetFallingRate(info.Info[j].ReleaseRate);

						int count = 0;
						for (long l = 0x16980; l != 0; l = (l * realAttack) >> 8)
							count++;
						info.Info[j].RealAttackRate = count * INTR_FREQUENCY;

						if (info.Info[j].SustainLevel == 0x7F)
							realSustainLev = 0;
						else
							realSustainLev = (0x10000 - sustainLevTable[info.Info[j].SustainLevel]) << 7;
						if (info.Info[j].DecayRate == 0x7F)
							info.Info[j].RealDecayRate = 0.001;
						else
						{
							count = 0x16980 / realDecay;//realSustainLev / realDecay;
							info.Info[j].RealDecayRate = count * INTR_FREQUENCY;
						}

						//rgn->bSustainInPctVol = false;
						//rgn->bSustainInDecibel = true;

						if (realSustainLev == 0)
							info.Info[j].RealSustainLevel = 1.0;
						else
						{
							//rgn->sustain_level = 20 * log10 ((92544.0-realSustainLev) / 92544.0);
							info.Info[j].RealSustainLevel = (double)(0x16980 - realSustainLev) / (double)0x16980;
						}


						count = 0x16980 / realRelease;		//we express release rate as time from maximum volume, not sustain level
						info.Info[j].RealReleaseRate = count * INTR_FREQUENCY;

						if (info.Info[j].Pan == 0)
							info.Info[j].RealPan = -1.0;
						else if (info.Info[j].Pan == 0x7F)
							info.Info[j].RealPan = 1.0;
						else if (info.Info[j].Pan == 0x40)
							info.Info[j].RealPan = 0;
						else
							info.Info[j].RealPan = (double)(info.Info[j].Pan - 63.5) / (double)0x40;



						if (info.Info[j].RealReleaseRate < .001)
							info.Info[j].RealReleaseRate = .001;
						if (info.Info[j].RealDecayRate < .001)
							info.Info[j].RealDecayRate = .001;
						if (info.Info[j].RealAttackRate < .001)
							info.Info[j].RealAttackRate = .001;

						long convAttack = (long)(Math.Ceiling((Math.Log(info.Info[j].RealAttackRate) / Math.Log((double)2)) * 1200 * 65536));
						long convDecay = (long)(Math.Ceiling((Math.Log(info.Info[j].RealDecayRate) / Math.Log((double)2)) * 1200 * 65536));
						long convSustainLev;
						/*if (info.Info[j].RealSustainLevel == -1)
							convSustainLev = 0x03e80000;		//sustain at full if no sustain level provided
						else if (true)
							convSustainLev = (long)(((96.0 + info.Info[j].RealSustainLevel) / 96.0) * 0x03e80000);		//the DLS envelope is a range from 0 to -96db. 
						*/
						convSustainLev = (long)(0x03e80000 * info.Info[j].RealSustainLevel);
						//convSustainLev = (long)(vgmrgn->sustain_level*0x03e80000);
						long convRelease = (long)Math.Ceiling((Math.Log(info.Info[j].RealReleaseRate) / Math.Log((double)2)) * 1200 * 65536);


						long pan = 0;
						//if (vgmrgn->bPanIn10thPctUnits)
						//	pan = vgmrgn->pan;
						//if (vgmrgn->pan != 0)	//by default pan is a double value between -1.0 and 1.0 (abs left and right)
						//	pan = (long)ceil((vgmrgn->pan*0x40) * 516031.49606299212598425196850394);
						if (info.Info[j].RealPan != 0) //by default pan is a double value between -1.0 and 1.0 (abs left and right)
							pan = (long)((info.Info[j].RealPan) * 32768000);

						info.Info[j].RealPan = pan;
						info.Info[j].RealAttackRate = convAttack;
						info.Info[j].RealDecayRate = convDecay;
						info.Info[j].RealReleaseRate = convRelease;
						info.Info[j].RealSustainLevel = convSustainLev;

					}
					s.Data.Ins[i].iInfo = info;
				}

			}
			return s;
		}
		private static ushort GetFallingRate(byte DecayTime)
		{
			ulong realDecay;
			if (DecayTime == 0x7F)
				realDecay = 0xFFFF;
			else if (DecayTime == 0x7E)
				realDecay = 0x3C00;
			else if (DecayTime < 0x32)
			{
				realDecay = DecayTime * 2ul;
				++realDecay;
				realDecay &= 0xFFFF;
			}
			else
			{
				realDecay = 0x1E00;
				DecayTime = (byte)(0x7E - DecayTime);
				realDecay /= DecayTime;		//there is a whole subroutine that seems to resolve simply to this.  I have tested all cases
				realDecay &= 0xFFFF;
			}
			return (ushort)realDecay;
		}
		public static void writeDLS(string file, Sbnk s)
		{
			byte[] b = writeDLS(s);
			File.Create(file).Close();
			File.WriteAllBytes(file, b);
		}
		public static byte[] writeDLS(Sbnk s)
		{
			List<KeyValuePair<int, int>> ssss = new List<KeyValuePair<int, int>>();
			List<SDAT.WAV.ArchivoWAV> wavv = new List<SDAT.WAV.ArchivoWAV>();
			int coun = 0;
			for (int i = 0; i < s.Data.Ins.Length; i++)
			{
				if (s.Data.Ins[i].fRecord == 0)
				{
					iRecord0 info = (iRecord0)s.Data.Ins[i].iInfo;
				}
				else if (s.Data.Ins[i].fRecord < 16)
				{
					coun++;
					iRecord_16 info = (iRecord_16)s.Data.Ins[i].iInfo;
					if (!ssss.Contains(new KeyValuePair<int, int>(info.nrSwar, info.nrSwav)))
					{
						ssss.Add(new KeyValuePair<int, int>(info.nrSwar, info.nrSwav));
						wavv.Add(SDAT.SWAV.ConvertirAWAV(info.WaveData));
					}
				}
				else if (s.Data.Ins[i].fRecord == 16)
				{
					coun++;
					iRecord16 info = (iRecord16)s.Data.Ins[i].iInfo;
					int nr = info.uNote - info.lNote + 1;
					for (int j = 0; j < nr; j++)
					{
						if (!ssss.Contains(new KeyValuePair<int, int>(info.Info[j].nrSwar, info.Info[j].nrSwav)))
						{
							ssss.Add(new KeyValuePair<int, int>(info.Info[j].nrSwar, info.Info[j].nrSwav));
							wavv.Add(SDAT.SWAV.ConvertirAWAV(info.Info[j].WaveData));
						}
					}
				}
				else if (s.Data.Ins[i].fRecord == 17)
				{
					coun++;
					iRecord17 info = (iRecord17)s.Data.Ins[i].iInfo;
					for (int j = 0; j < info.nr; j++)
					{
						if (!ssss.Contains(new KeyValuePair<int, int>(info.Info[j].nrSwar, info.Info[j].nrSwav)))
						{
							ssss.Add(new KeyValuePair<int, int>(info.Info[j].nrSwar, info.Info[j].nrSwav));
							wavv.Add(SDAT.SWAV.ConvertirAWAV(info.Info[j].WaveData));
						}
					}
				}
			}
			MemoryStream m = new MemoryStream();
			EndianBinaryWriter ew = new EndianBinaryWriter(m, Endianness.LittleEndian);
			List<long> offset = new List<long>();//write size -= 4;
			long curpos = 0;
			ew.Write("RIFF", Encoding.ASCII, false);
			offset.Add(ew.BaseStream.Position);
			ew.Write((Int32)0);
			{
				ew.Write("DLS colh", Encoding.ASCII, false);
				ew.Write((Int32)0x04);
				{
					ew.Write((Int32)coun);
				}
				ew.Write("LIST", Encoding.ASCII, false);
				offset.Add(ew.BaseStream.Position);
				ew.Write((Int32)0);
				{
					ew.Write("lins", Encoding.ASCII, false);
					for (int i = 0; i < s.Data.nCount; i++)
					{
						if (s.Data.Ins[i].fRecord == 0) { continue; }
						ew.Write("LIST", Encoding.ASCII, false);
						offset.Add(ew.BaseStream.Position);
						ew.Write((Int32)0);
						{
							ew.Write("ins ", Encoding.ASCII, false);
							ew.Write("insh", Encoding.ASCII, false);
							//offset.Add(ew.BaseStream.Position);
							ew.Write((Int32)0x0C);
							{
								if (s.Data.Ins[i].fRecord < 16)
								{
									iRecord_16 info = (iRecord_16)s.Data.Ins[i].iInfo;
									ew.Write((Int32)1);
									ew.Write((Int32)0);
									ew.Write((Int32)i);
									ew.Write("LIST", Encoding.ASCII, false);
									offset.Add(ew.BaseStream.Position);
									ew.Write((Int32)0);
									{
										ew.Write("lrgn", Encoding.ASCII, false);
										ew.Write("LIST", Encoding.ASCII, false);
										offset.Add(ew.BaseStream.Position);
										ew.Write((Int32)0);
										{
											ew.Write("rgn2", Encoding.ASCII, false);
											ew.Write("rgnh", Encoding.ASCII, false);
											//offset.Add(ew.BaseStream.Position);
											ew.Write((Int32)0x0E);
											{
												ew.Write((Int16)0);//lower note
												ew.Write((Int16)0x7F);//upper note
												ew.Write((Int16)0);//lower velocity
												ew.Write((Int16)0x7F);//upper velocity
												ew.Write((Int16)1);
												ew.Write((Int16)0);
												ew.Write((Int16)1);
												ew.Write("wsmp", Encoding.ASCII, false);
												offset.Add(ew.BaseStream.Position);
												ew.Write((Int32)0);
												{
													ew.Write((Int32)20);
													ew.Write((Int16)info.Note);
													ew.Write((Int16)0);
													ew.Write((Int32)0);
													ew.Write((Int32)1);
													ew.Write((Int32)info.WaveData.data.info.bLoop);
													if (info.WaveData.data.info.bLoop == 1)									//if it loops, write the loop structure
													{
														ew.Write((Int32)16);
														int dataLength;
														int nonlooplength = (int)info.WaveData.data.info.nNonLoopLen * 4;
														int loopoffset = info.WaveData.data.info.nLoopOffset * 4;
														if (info.WaveData.data.info.nWaveType == 2)
														{
															dataLength = (int)(loopoffset + nonlooplength - 4);
														}
														else
														{
															dataLength = (int)(loopoffset + nonlooplength);
														}
														int loopStartMeasure = 0;
														if (info.WaveData.data.info.nWaveType == 2)
														{
															loopStartMeasure = 1;
															loopoffset *= 2;
															loopoffset = loopoffset - 8 + 1;
															nonlooplength = (dataLength * 2 + 1) - loopoffset;
														}


														int origFormatBytesPerSamp = (info.WaveData.data.info.nWaveType == 0 ? 8 : 16) / 8;
														double compressionRatio = 1.0d;

														// If the sample loops, but the loop length is 0, then assume the length should
														// extend to the end of the sample.
														//if (info.Info[j].WaveData.data.info.bLoop == 1 && nonlooplength == 0)
														//    nonlooplength = info.Info[j].WaveData.data.info. - loop.loopStart;

														int cSampleLoops = info.WaveData.data.info.bLoop;
														int ulLoopType = 0;
														int ulLoopStart = (loopStartMeasure == 0) ?			//In DLS, the value is in number of samples
															(loopoffset * (int)compressionRatio) / origFormatBytesPerSamp ://(16/8) :		//if the val is a raw offset of the original format, multiply it by the compression ratio
															loopoffset /** origFormatBytesPerSamp * compressionRatio / origFormatBytesPerSamp*/;//(16/8);	 //if the value is in samples, multiply by bytes per sample to get raw offset of original format, then multiply by compression ratio to get raw offset in standard wav, then divide bytes bytesPerSamp of standard wave (2)
														int ulLoopLength = (loopStartMeasure == 0) ?			//In DLS, the value is in number of samples
															(nonlooplength * (int)compressionRatio) / origFormatBytesPerSamp ://(16/8)  :	//if it's in raw bytes, multiply by compressionRatio to convert to Raw length in new format, and divide by bytesPerSamp of a 16 bit standard wave (16bits/8 bits per byte)
															nonlooplength /** origFormatBytesPerSamp * compressionRatio) / origFormatBytesPerSamp*/;//(16/8);





														ew.Write((Int32)0);			//ulLoopType
														ew.Write((Int32)ulLoopStart - 25);
														ew.Write((Int32)ulLoopLength);
													}
												}
												curpos = ew.BaseStream.Position;
												ew.BaseStream.Position = offset.Last();
												ew.Write((Int32)(curpos - offset.Last() - 4));
												ew.BaseStream.Position = curpos;
												offset.Remove(offset.Last());
												ew.Write("wlnk", Encoding.ASCII, false);
												//offset.Add(ew.BaseStream.Position);
												ew.Write((Int32)0x0C);
												{
													ew.Write((Int16)0);
													ew.Write((Int16)0);
													ew.Write((Int32)1);
													ew.Write((Int32)ssss.IndexOf(new KeyValuePair<int, int>(info.nrSwar, info.nrSwav)));
													ew.Write("LIST", Encoding.ASCII, false);
													offset.Add(ew.BaseStream.Position);
													ew.Write((Int32)0);
													{
														ew.Write("lar2", Encoding.ASCII, false);
														ew.Write("art2", Encoding.ASCII, false);
														offset.Add(ew.BaseStream.Position);
														ew.Write((Int32)0);
														{
															ew.Write((Int32)8);
															ew.Write((Int32)5);
															//pan
															ew.Write((Int16)0);//CONN_SRC_NONE
															ew.Write((Int16)0);//CONN_SRC_NONE
															ew.Write((Int16)4);//CONN_DST_PAN
															ew.Write((Int16)0);//CONN_TRN_NONE
															ew.Write((UInt32)info.RealPan);
															//attack
															ew.Write((Int16)0);//CONN_SRC_NONE
															ew.Write((Int16)0);//CONN_SRC_NONE
															ew.Write((Int16)0x0206);//CONN_DST_EG1_DTIME
															ew.Write((Int16)0);//CONN_TRN_NONE
															ew.Write((UInt32)info.RealAttackRate);//(float)info.RealAttackRate);
															//decay
															ew.Write((Int16)0);//CONN_SRC_NONE
															ew.Write((Int16)0);//CONN_SRC_NONE
															ew.Write((Int16)0x0207);//CONN_DST_EG1_DECAYTIME
															ew.Write((Int16)0);//CONN_TRN_NONE
															ew.Write((UInt32)info.RealDecayRate);
															//sustain
															ew.Write((Int16)0);//CONN_SRC_NONE
															ew.Write((Int16)0);//CONN_SRC_NONE
															ew.Write((Int16)0x020A);//CONN_DST_EG1_SUSTAINLEVEL
															ew.Write((Int16)0);//CONN_TRN_NONE
															ew.Write((UInt32)info.RealSustainLevel);
															//release
															ew.Write((Int16)0);//CONN_SRC_NONE
															ew.Write((Int16)0);//CONN_SRC_NONE
															ew.Write((Int16)0x0209);//CONN_DST_EG1_RELEASETIME
															ew.Write((Int16)0);//CONN_TRN_NONE
															ew.Write((UInt32)info.RealReleaseRate);
														}
														curpos = ew.BaseStream.Position;
														ew.BaseStream.Position = offset.Last();
														ew.Write((Int32)(curpos - offset.Last() - 4));
														ew.BaseStream.Position = curpos;
														offset.Remove(offset.Last());
													}
													curpos = ew.BaseStream.Position;
													ew.BaseStream.Position = offset.Last();
													ew.Write((Int32)(curpos - offset.Last() - 4));
													ew.BaseStream.Position = curpos;
													offset.Remove(offset.Last());
												}
											}
										}
										curpos = ew.BaseStream.Position;
										ew.BaseStream.Position = offset.Last();
										ew.Write((Int32)(curpos - offset.Last() - 4));
										ew.BaseStream.Position = curpos;
										offset.Remove(offset.Last());
									}
									curpos = ew.BaseStream.Position;
									ew.BaseStream.Position = offset.Last();
									ew.Write((Int32)(curpos - offset.Last() - 4));
									ew.BaseStream.Position = curpos;
									offset.Remove(offset.Last());
								}
								else if (s.Data.Ins[i].fRecord == 16)
								{
									iRecord16 info = (iRecord16)s.Data.Ins[i].iInfo;
									int nr = info.uNote - info.lNote + 1;
									ew.Write((Int32)nr);
									ew.Write((Int32)(i == 127 ? 0x80000000 : 0));
									ew.Write((Int32)i);

									ew.Write("LIST", Encoding.ASCII, false);
									offset.Add(ew.BaseStream.Position);
									ew.Write((Int32)0);
									{
										ew.Write("lrgn", Encoding.ASCII, false);
										for (int j = 0; j < nr; j++)
										{
											ew.Write("LIST", Encoding.ASCII, false);
											offset.Add(ew.BaseStream.Position);
											ew.Write((Int32)0);
											{
												ew.Write("rgn2", Encoding.ASCII, false);
												ew.Write("rgnh", Encoding.ASCII, false);
												//offset.Add(ew.BaseStream.Position);
												ew.Write((Int32)0x0E);
												{
													ew.Write((Int16)(info.lNote + j));//lower note
													ew.Write((Int16)(info.lNote + j));//upper note
													ew.Write((Int16)0);//lower velocity
													ew.Write((Int16)0x7F);//upper velocity
													ew.Write((Int16)1);
													ew.Write((Int16)0);
													ew.Write((Int16)1);
													ew.Write("wsmp", Encoding.ASCII, false);
													offset.Add(ew.BaseStream.Position);
													ew.Write((Int32)0);
													{
														ew.Write((Int32)20);
														ew.Write((Int16)info.Info[j].Note);
														ew.Write((Int16)0);
														ew.Write((Int32)0);
														ew.Write((Int32)1);
														ew.Write((Int32)info.Info[j].WaveData.data.info.bLoop);
														if (info.Info[j].WaveData.data.info.bLoop == 1)									//if it loops, write the loop structure
														{
															ew.Write((Int32)16);
															int dataLength;
															int nonlooplength = (int)info.Info[j].WaveData.data.info.nNonLoopLen * 4;
															int loopoffset = info.Info[j].WaveData.data.info.nLoopOffset * 4;
															if (info.Info[j].WaveData.data.info.nWaveType == 2)
															{
																dataLength = (int)(loopoffset + nonlooplength - 4);
															}
															else
															{
																dataLength = (int)(loopoffset + nonlooplength);
															}
															int loopStartMeasure = 0;
															if (info.Info[j].WaveData.data.info.nWaveType == 2)
															{
																loopStartMeasure = 1;
																loopoffset *= 2;
																loopoffset = loopoffset - 8 + 1;
																nonlooplength = (dataLength * 2 + 1) - loopoffset;
															}


															int origFormatBytesPerSamp = (info.Info[j].WaveData.data.info.nWaveType == 0 ? 8 : 16) / 8;
															double compressionRatio = 1.0d;

															// If the sample loops, but the loop length is 0, then assume the length should
															// extend to the end of the sample.
															//if (info.Info[j].WaveData.data.info.bLoop == 1 && nonlooplength == 0)
															//    nonlooplength = info.Info[j].WaveData.data.info. - loop.loopStart;

															int cSampleLoops = info.Info[j].WaveData.data.info.bLoop;
															int ulLoopType = 0;
															int ulLoopStart = (loopStartMeasure == 0) ?			//In DLS, the value is in number of samples
																(loopoffset * (int)compressionRatio) / origFormatBytesPerSamp ://(16/8) :		//if the val is a raw offset of the original format, multiply it by the compression ratio
																loopoffset /** origFormatBytesPerSamp * compressionRatio / origFormatBytesPerSamp*/;//(16/8);	 //if the value is in samples, multiply by bytes per sample to get raw offset of original format, then multiply by compression ratio to get raw offset in standard wav, then divide bytes bytesPerSamp of standard wave (2)
															int ulLoopLength = (loopStartMeasure == 0) ?			//In DLS, the value is in number of samples
																(nonlooplength * (int)compressionRatio) / origFormatBytesPerSamp ://(16/8)  :	//if it's in raw bytes, multiply by compressionRatio to convert to Raw length in new format, and divide by bytesPerSamp of a 16 bit standard wave (16bits/8 bits per byte)
																nonlooplength /** origFormatBytesPerSamp * compressionRatio) / origFormatBytesPerSamp*/;//(16/8);


															ew.Write((Int32)0);			//ulLoopType
															ew.Write((Int32)ulLoopStart);
															ew.Write((Int32)ulLoopLength);
														}
													}
													curpos = ew.BaseStream.Position;
													ew.BaseStream.Position = offset.Last();
													ew.Write((Int32)(curpos - offset.Last() - 4));
													ew.BaseStream.Position = curpos;
													offset.Remove(offset.Last());
													ew.Write("wlnk", Encoding.ASCII, false);
													//offset.Add(ew.BaseStream.Position);
													ew.Write((Int32)0x0C);
													{
														ew.Write((Int16)0);
														ew.Write((Int16)0);
														ew.Write((Int32)1);
														ew.Write((Int32)ssss.IndexOf(new KeyValuePair<int, int>(info.Info[j].nrSwar, info.Info[j].nrSwav)));
														ew.Write("LIST", Encoding.ASCII, false);
														offset.Add(ew.BaseStream.Position);
														ew.Write((Int32)0);
														{
															ew.Write("lar2", Encoding.ASCII, false);
															ew.Write("art2", Encoding.ASCII, false);
															offset.Add(ew.BaseStream.Position);
															ew.Write((Int32)0);
															{
																ew.Write((Int32)8);
																ew.Write((Int32)5);
																//pan
																ew.Write((Int16)0);//CONN_SRC_NONE
																ew.Write((Int16)0);//CONN_SRC_NONE
																ew.Write((Int16)4);//CONN_DST_PAN
																ew.Write((Int16)0);//CONN_TRN_NONE
																ew.Write((UInt32)info.Info[j].RealPan);
																//attack
																ew.Write((Int16)0);//CONN_SRC_NONE
																ew.Write((Int16)0);//CONN_SRC_NONE
																ew.Write((Int16)0x0206);//CONN_DST_EG1_DTIME
																ew.Write((Int16)0);//CONN_TRN_NONE
																ew.Write((UInt32)info.Info[j].RealAttackRate);
																//decay
																ew.Write((Int16)0);//CONN_SRC_NONE
																ew.Write((Int16)0);//CONN_SRC_NONE
																ew.Write((Int16)0x0207);//CONN_DST_EG1_DECAYTIME
																ew.Write((Int16)0);//CONN_TRN_NONE
																ew.Write((UInt32)info.Info[j].RealDecayRate);
																//sustain
																ew.Write((Int16)0);//CONN_SRC_NONE
																ew.Write((Int16)0);//CONN_SRC_NONE
																ew.Write((Int16)0x020A);//CONN_DST_EG1_SUSTAINLEVEL
																ew.Write((Int16)0);//CONN_TRN_NONE
																ew.Write((UInt32)info.Info[j].RealSustainLevel);
																//release
																ew.Write((Int16)0);//CONN_SRC_NONE
																ew.Write((Int16)0);//CONN_SRC_NONE
																ew.Write((Int16)0x0209);//CONN_DST_EG1_RELEASETIME
																ew.Write((Int16)0);//CONN_TRN_NONE
																ew.Write((UInt32)info.Info[j].RealReleaseRate);
															}
															curpos = ew.BaseStream.Position;
															ew.BaseStream.Position = offset.Last();
															ew.Write((Int32)(curpos - offset.Last() - 4));
															ew.BaseStream.Position = curpos;
															offset.Remove(offset.Last());
														}
														curpos = ew.BaseStream.Position;
														ew.BaseStream.Position = offset.Last();
														ew.Write((Int32)(curpos - offset.Last() - 4));
														ew.BaseStream.Position = curpos;
														offset.Remove(offset.Last());
													}
												}
											}
											curpos = ew.BaseStream.Position;
											ew.BaseStream.Position = offset.Last();
											ew.Write((Int32)(curpos - offset.Last() - 4));
											ew.BaseStream.Position = curpos;
											offset.Remove(offset.Last());
										}

									}
									curpos = ew.BaseStream.Position;
									ew.BaseStream.Position = offset.Last();
									ew.Write((Int32)(curpos - offset.Last() - 4));
									ew.BaseStream.Position = curpos;
									offset.Remove(offset.Last());
								}
								else if (s.Data.Ins[i].fRecord == 17)
								{
									iRecord17 info = (iRecord17)s.Data.Ins[i].iInfo;
									ew.Write((Int32)info.nr);
									ew.Write((Int32)0);
									ew.Write((Int32)i);

									ew.Write("LIST", Encoding.ASCII, false);
									offset.Add(ew.BaseStream.Position);
									ew.Write((Int32)0);
									{
										ew.Write("lrgn", Encoding.ASCII, false);
										for (int j = 0; j < info.nr; j++)
										{
											ew.Write("LIST", Encoding.ASCII, false);
											offset.Add(ew.BaseStream.Position);
											ew.Write((Int32)0);
											{
												ew.Write("rgn2", Encoding.ASCII, false);
												ew.Write("rgnh", Encoding.ASCII, false);
												//offset.Add(ew.BaseStream.Position);
												ew.Write((Int32)0x0E);
												{
													ew.Write((Int16)(j == 0 ? 0 : info.Regions[j - 1] + 1));//lower note
													ew.Write((Int16)info.Regions[j]);//upper note
													ew.Write((Int16)0);//lower velocity
													ew.Write((Int16)0x7F);//upper velocity
													ew.Write((Int16)1);
													ew.Write((Int16)0);
													ew.Write((Int16)1);
													ew.Write("wsmp", Encoding.ASCII, false);
													offset.Add(ew.BaseStream.Position);
													ew.Write((Int32)0);
													{
														ew.Write((Int32)20);
														ew.Write((Int16)info.Info[j].Note);
														ew.Write((Int16)0);
														ew.Write((Int32)0);
														ew.Write((Int32)1);
														ew.Write((Int32)info.Info[j].WaveData.data.info.bLoop);
														if (info.Info[j].WaveData.data.info.bLoop == 1)									//if it loops, write the loop structure
														{
															ew.Write((Int32)16);
															int dataLength;
															int nonlooplength = (int)info.Info[j].WaveData.data.info.nNonLoopLen * 4;
															int loopoffset = info.Info[j].WaveData.data.info.nLoopOffset * 4;
															if (info.Info[j].WaveData.data.info.nWaveType == 2)
															{
																dataLength = (int)(loopoffset + nonlooplength - 4);
															}
															else
															{
																dataLength = (int)(loopoffset + nonlooplength);
															}
															int loopStartMeasure = 0;
															if (info.Info[j].WaveData.data.info.nWaveType == 2)
															{
																loopStartMeasure = 1;
																loopoffset *= 2;
																loopoffset = loopoffset - 8 + 1;
																nonlooplength = (dataLength * 2 + 1) - loopoffset;
															}


															int origFormatBytesPerSamp = (info.Info[j].WaveData.data.info.nWaveType == 0 ? 8 : 16) / 8;
															double compressionRatio = 1.0d;

															// If the sample loops, but the loop length is 0, then assume the length should
															// extend to the end of the sample.
															//if (info.Info[j].WaveData.data.info.bLoop == 1 && nonlooplength == 0)
															//    nonlooplength = info.Info[j].WaveData.data.info. - loop.loopStart;

															int cSampleLoops = info.Info[j].WaveData.data.info.bLoop;
															int ulLoopType = 0;
															int ulLoopStart = (loopStartMeasure == 0) ?			//In DLS, the value is in number of samples
																(loopoffset * (int)compressionRatio) / origFormatBytesPerSamp ://(16/8) :		//if the val is a raw offset of the original format, multiply it by the compression ratio
																loopoffset /** origFormatBytesPerSamp * compressionRatio / origFormatBytesPerSamp*/;//(16/8);	 //if the value is in samples, multiply by bytes per sample to get raw offset of original format, then multiply by compression ratio to get raw offset in standard wav, then divide bytes bytesPerSamp of standard wave (2)
															int ulLoopLength = (loopStartMeasure == 0) ?			//In DLS, the value is in number of samples
																(nonlooplength * (int)compressionRatio) / origFormatBytesPerSamp ://(16/8)  :	//if it's in raw bytes, multiply by compressionRatio to convert to Raw length in new format, and divide by bytesPerSamp of a 16 bit standard wave (16bits/8 bits per byte)
																nonlooplength /** origFormatBytesPerSamp * compressionRatio) / origFormatBytesPerSamp*/;//(16/8);


															ew.Write((Int32)0);			//ulLoopType
															ew.Write((Int32)ulLoopStart);
															ew.Write((Int32)ulLoopLength);
														}
													}
													curpos = ew.BaseStream.Position;
													ew.BaseStream.Position = offset.Last();
													ew.Write((Int32)(curpos - offset.Last() - 4));
													ew.BaseStream.Position = curpos;
													offset.Remove(offset.Last());
													ew.Write("wlnk", Encoding.ASCII, false);
													//offset.Add(ew.BaseStream.Position);
													ew.Write((Int32)0x0C);
													{
														ew.Write((Int16)0);
														ew.Write((Int16)0);
														ew.Write((Int32)1);
														ew.Write((Int32)ssss.IndexOf(new KeyValuePair<int, int>(info.Info[j].nrSwar, info.Info[j].nrSwav)));
														ew.Write("LIST", Encoding.ASCII, false);
														offset.Add(ew.BaseStream.Position);
														ew.Write((Int32)0);
														{
															ew.Write("lar2", Encoding.ASCII, false);
															ew.Write("art2", Encoding.ASCII, false);
															offset.Add(ew.BaseStream.Position);
															ew.Write((Int32)0);
															{
																ew.Write((Int32)8);
																ew.Write((Int32)5);
																//pan
																ew.Write((Int16)0);//CONN_SRC_NONE
																ew.Write((Int16)0);//CONN_SRC_NONE
																ew.Write((Int16)4);//CONN_DST_PAN
																ew.Write((Int16)0);//CONN_TRN_NONE
																ew.Write((UInt32)info.Info[j].RealPan);
																//attack
																ew.Write((Int16)0);//CONN_SRC_NONE
																ew.Write((Int16)0);//CONN_SRC_NONE
																ew.Write((Int16)0x0206);//CONN_DST_EG1_DTIME
																ew.Write((Int16)0);//CONN_TRN_NONE
																ew.Write((UInt32)info.Info[j].RealAttackRate);
																//decay
																ew.Write((Int16)0);//CONN_SRC_NONE
																ew.Write((Int16)0);//CONN_SRC_NONE
																ew.Write((Int16)0x0207);//CONN_DST_EG1_DECAYTIME
																ew.Write((Int16)0);//CONN_TRN_NONE
																ew.Write((UInt32)info.Info[j].RealDecayRate);
																//sustain
																ew.Write((Int16)0);//CONN_SRC_NONE
																ew.Write((Int16)0);//CONN_SRC_NONE
																ew.Write((Int16)0x020A);//CONN_DST_EG1_SUSTAINLEVEL
																ew.Write((Int16)0);//CONN_TRN_NONE
																ew.Write((UInt32)info.Info[j].RealSustainLevel);
																//release
																ew.Write((Int16)0);//CONN_SRC_NONE
																ew.Write((Int16)0);//CONN_SRC_NONE
																ew.Write((Int16)0x0209);//CONN_DST_EG1_RELEASETIME
																ew.Write((Int16)0);//CONN_TRN_NONE
																ew.Write((UInt32)info.Info[j].RealReleaseRate);
															}
															curpos = ew.BaseStream.Position;
															ew.BaseStream.Position = offset.Last();
															ew.Write((Int32)(curpos - offset.Last() - 4));
															ew.BaseStream.Position = curpos;
															offset.Remove(offset.Last());
														}
														curpos = ew.BaseStream.Position;
														ew.BaseStream.Position = offset.Last();
														ew.Write((Int32)(curpos - offset.Last() - 4));
														ew.BaseStream.Position = curpos;
														offset.Remove(offset.Last());
													}
												}
											}
											curpos = ew.BaseStream.Position;
											ew.BaseStream.Position = offset.Last();
											ew.Write((Int32)(curpos - offset.Last() - 4));
											ew.BaseStream.Position = curpos;
											offset.Remove(offset.Last());
										}
									}
									curpos = ew.BaseStream.Position;
									ew.BaseStream.Position = offset.Last();
									ew.Write((Int32)(curpos - offset.Last() - 4));
									ew.BaseStream.Position = curpos;
									offset.Remove(offset.Last());
								}
								ew.Write("LIST", Encoding.ASCII, false);
								offset.Add(ew.BaseStream.Position);
								ew.Write((Int32)0);
								{
									ew.Write("INFO", Encoding.ASCII, false);
									ew.Write("INAM", Encoding.ASCII, false);
									offset.Add(ew.BaseStream.Position);
									ew.Write((Int32)0);
									{
										ew.Write("Unnamed Instrument", Encoding.ASCII, false);
										ew.Write((Int16)0);
									}
									curpos = ew.BaseStream.Position;
									ew.BaseStream.Position = offset.Last();
									ew.Write((Int32)(curpos - offset.Last() - 4));
									ew.BaseStream.Position = curpos;
									offset.Remove(offset.Last());
								}
								curpos = ew.BaseStream.Position;
								ew.BaseStream.Position = offset.Last();
								ew.Write((Int32)(curpos - offset.Last() - 4));
								ew.BaseStream.Position = curpos;
								offset.Remove(offset.Last());
							}
						}
						curpos = ew.BaseStream.Position;
						ew.BaseStream.Position = offset.Last();
						ew.Write((Int32)(curpos - offset.Last() - 4));
						ew.BaseStream.Position = curpos;
						offset.Remove(offset.Last());
					}
				}
				curpos = ew.BaseStream.Position;
				ew.BaseStream.Position = offset.Last();
				ew.Write((Int32)(curpos - offset.Last() - 4));
				ew.BaseStream.Position = curpos;
				offset.Remove(offset.Last());
				ew.Write("ptbl", Encoding.ASCII, false);
				offset.Add(ew.BaseStream.Position);
				ew.Write((Int32)0);
				{
					ew.Write((Int32)8);
					ew.Write((Int32)ssss.Count);
					int off = 0;
					for (int j = 0; j < ssss.Count; j++)
					{
						ew.Write((Int32)off);
						off += (int)wavv[j].wave.data.data.Length + 12 + 8 + 18 + 8 + 12 + 8 + 0xE;
					}
				}
				curpos = ew.BaseStream.Position;
				ew.BaseStream.Position = offset.Last();
				ew.Write((Int32)(curpos - offset.Last() - 4));
				ew.BaseStream.Position = curpos;
				offset.Remove(offset.Last());
				ew.Write("LIST", Encoding.ASCII, false);
				offset.Add(ew.BaseStream.Position);
				ew.Write((Int32)0);
				{
					ew.Write("wvpl", Encoding.ASCII, false);
					for (int j = 0; j < wavv.Count; j++)
					{
						ew.Write("LIST", Encoding.ASCII, false);
						offset.Add(ew.BaseStream.Position);
						ew.Write((Int32)0);
						{
							ew.Write("wave", Encoding.ASCII, false);
							ew.Write("fmt ", Encoding.ASCII, false);
							ew.Write(0x12);
							ew.Write(Convert.ToUInt16(wavv[j].wave.fmt.audioFormat));
							ew.Write(wavv[j].wave.fmt.numChannels);
							ew.Write(wavv[j].wave.fmt.sampleRate);
							ew.Write(wavv[j].wave.fmt.byteRate);
							ew.Write(wavv[j].wave.fmt.blockAlign);
							ew.Write(wavv[j].wave.fmt.bitsPerSample);
							ew.Write((Int16)0);
							ew.Write("data", Encoding.ASCII, false);
							ew.Write(wavv[j].wave.data.chunkSize);
							ew.Write(wavv[j].wave.data.data, 0, wavv[j].wave.data.data.Length);
							ew.Write("LIST", Encoding.ASCII, false);
							offset.Add(ew.BaseStream.Position);
							ew.Write((Int32)0);
							{
								ew.Write("INFO", Encoding.ASCII, false);
								ew.Write("INAM", Encoding.ASCII, false);
								offset.Add(ew.BaseStream.Position);
								ew.Write((Int32)0);
								{
									ew.Write("Unnamed Wave", Encoding.ASCII, false);
									ew.Write((Int16)0);
								}
								curpos = ew.BaseStream.Position;
								ew.BaseStream.Position = offset.Last();
								ew.Write((Int32)(curpos - offset.Last() - 4));
								ew.BaseStream.Position = curpos;
								offset.Remove(offset.Last());
							}
							curpos = ew.BaseStream.Position;
							ew.BaseStream.Position = offset.Last();
							ew.Write((Int32)(curpos - offset.Last() - 4));
							ew.BaseStream.Position = curpos;
							offset.Remove(offset.Last());
						}
						curpos = ew.BaseStream.Position;
						ew.BaseStream.Position = offset.Last();
						ew.Write((Int32)(curpos - offset.Last() - 4));
						ew.BaseStream.Position = curpos;
						offset.Remove(offset.Last());
					}
				}
				curpos = ew.BaseStream.Position;
				ew.BaseStream.Position = offset.Last();
				ew.Write((Int32)(curpos - offset.Last() - 4));
				ew.BaseStream.Position = curpos;
				offset.Remove(offset.Last());
				ew.Write("LIST", Encoding.ASCII, false);
				offset.Add(ew.BaseStream.Position);
				ew.Write((Int32)0);
				{
					ew.Write("INFO", Encoding.ASCII, false);
					ew.Write("INAM", Encoding.ASCII, false);
					offset.Add(ew.BaseStream.Position);
					ew.Write((Int32)0);
					{
						ew.Write("Unnamed Instrumentset", Encoding.ASCII, false);
						ew.Write((Int16)0);
					}
					curpos = ew.BaseStream.Position;
					ew.BaseStream.Position = offset.Last();
					ew.Write((Int32)(curpos - offset.Last() - 4));
					ew.BaseStream.Position = curpos;
					offset.Remove(offset.Last());
				}
				curpos = ew.BaseStream.Position;
				ew.BaseStream.Position = offset.Last();
				ew.Write((Int32)(curpos - offset.Last() - 4));
				ew.BaseStream.Position = curpos;
				offset.Remove(offset.Last());
			}
			curpos = ew.BaseStream.Position;
			ew.BaseStream.Position = offset.Last();
			ew.Write((Int32)(curpos - offset.Last() - 4));
			ew.BaseStream.Position = curpos;
			offset.Remove(offset.Last());
			byte[] bbbb = m.ToArray();
			ew.Close();
			return bbbb;
		}
		public struct SbnkInstrument
		{
			public byte fRecord;	// can be either 0, 1..4, 16 or 17
			public Int16 nOffset;	// absolute offset of the data in file
			public byte reserved;	// must be zero

			public object iInfo;
		}

		public struct Sbnk
		{
			public string type;   // 'SBNK'
			public byte[] magic;	// 0x0100feff
			public Int32 nFileSize;	// Size of this SBNK file
			public Int16 nSize;	// Size of this structure = 16
			public Int16 nBlock;	// Number of Blocks = 1
			public data Data;
			public struct data
			{
				public string type;		// 'DATA'
				public Int32 nSize;		// Size of this structure
				public Int32[] reserved;	// reserved 0s, for use in runtime
				public Int32 nCount;		// number of instrument
				public SbnkInstrument[] Ins;
			}
		}

		public struct iRecord0
		{

		}
		public struct iRecord_16
		{
			public Int16 nrSwav; // the swav used
			public Int16 nrSwar; // the swar used. NB. cross-reference to "1.3.2 Info Block - Entry, Record 2 BANK" 
			public byte Note; // 0..127
			public byte AttackRate; // 0..127
			public double RealAttackRate;
			public byte DecayRate;	// 0..127
			public double RealDecayRate;
			public byte SustainLevel; // 0..127
			public double RealSustainLevel;
			public byte ReleaseRate; // 0..127
			public double RealReleaseRate;
			public byte Pan; // 0..127, 64 = middle
			public double RealPan;
			public SDAT.SWAV.ArchivoSWAV WaveData;
		}
		public struct iRecord16
		{
			public byte lNote;
			public byte uNote;
			public info[] Info;
			public struct info
			{
				public byte[] Unknown; // usually == 01 00
				public Int16 nrSwav; // the swav used
				public Int16 nrSwar; // the swar used. NB. cross-reference to "1.3.2 Info Block - Entry, Record 2 BANK" 
				public byte Note; // 0..127
				public byte AttackRate; // 0..127
				public double RealAttackRate;
				public byte DecayRate;	// 0..127
				public double RealDecayRate;
				public byte SustainLevel; // 0..127
				public double RealSustainLevel;
				public byte ReleaseRate; // 0..127
				public double RealReleaseRate;
				public byte Pan; // 0..127, 64 = middle
				public double RealPan;
				public SDAT.SWAV.ArchivoSWAV WaveData;
			}
		}
		public struct iRecord17
		{
			public byte[] Regions;
			public info[] Info;
			public int nr;
			public struct info
			{
				public byte[] Unknown; // usually == 01 00
				public Int16 nrSwav; // the swav used
				public Int16 nrSwar; // the swar used. NB. cross-reference to "1.3.2 Info Block - Entry, Record 2 BANK" 
				public byte Note; // 0..127
				public byte AttackRate; // 0..127
				public double RealAttackRate;
				public byte DecayRate;	// 0..127
				public double RealDecayRate;
				public byte SustainLevel; // 0..127
				public double RealSustainLevel;
				public byte ReleaseRate; // 0..127
				public double RealReleaseRate;
				public byte Pan; // 0..127, 64 = middle
				public double RealPan;
				public SDAT.SWAV.ArchivoSWAV WaveData;
			}
		}

		private void toolStripButton7_Click(object sender, EventArgs e)
		{
			if (saveFileDialog2.ShowDialog() == System.Windows.Forms.DialogResult.OK
				&& saveFileDialog2.FileName.Length > 0)
			{
				File.Create(saveFileDialog2.FileName).Close();
				File.WriteAllBytes(saveFileDialog2.FileName, dls);
			}
		}
	}
}
